digitalmars.D.learn - Reading and writing a text file
- Hytak (12/12) Mar 20 2005 Hi
- Hytak (3/15) Mar 20 2005 Well I forgot: what I want to do is to read the word after "MYWORD:" and...
- Derek Parnell (59/79) Mar 20 2005 Here is some code that finds a text string in a file. You can use someth...
- Hytak (2/81) Mar 20 2005
- AEon (28/44) Mar 20 2005 Derek Parnell says...
- AEon (8/20) Mar 20 2005 Forgot to ask about the new notation:
- Regan Heath (23/44) Mar 20 2005 I think it's a style choice. I agree that it's instructive, but I also
- AEon (6/13) Mar 20 2005 Ok... does the above alias have some evil side effects (type checking no...
- Regan Heath (20/33) Mar 20 2005 The one above, no, not as far as I can see. Firstly, because it doesn't ...
- AEon (6/13) Mar 20 2005 Ok... does the above alias have some evil side effects (type checking no...
- Derek Parnell (20/70) Mar 20 2005 LOL. I whipped up this code in ten minutes at 2:20AM so I expect it coul...
Hi I just try few things before starting a little program in D, and I will need to read and write things to a file. I know how to do it in C++ and a little bit in C, but the D's fonctions to read and write to file seems to be a mix of C and C++. What I want to to is to open a .txt and to search in it the word "MYWORRD". Do we have to use getc? What should it look like? I saw the functions read, write, append, ungetc and all but it should be nice someone write a deeper tutorial on them (does it exist?) I saw on http://www.quit-clan.de/docwiki/view.php?pageid=3 that there was some example, nice to look... but now really what I am looking for.
Mar 20 2005
Well I forgot: what I want to do is to read the word after "MYWORD:" and to store it into a char[] or a string. In article <d1k1n8$l0r$1 digitaldaemon.com>, Hytak says...Hi I just try few things before starting a little program in D, and I will need to read and write things to a file. I know how to do it in C++ and a little bit in C, but the D's fonctions to read and write to file seems to be a mix of C and C++. What I want to to is to open a .txt and to search in it the word "MYWORRD". Do we have to use getc? What should it look like? I saw the functions read, write, append, ungetc and all but it should be nice someone write a deeper tutorial on them (does it exist?) I saw on http://www.quit-clan.de/docwiki/view.php?pageid=3 that there was some example, nice to look... but now really what I am looking for.
Mar 20 2005
On Sun, 20 Mar 2005 15:05:41 +0000 (UTC), Hytak wrote:Well I forgot: what I want to do is to read the word after "MYWORD:" and to store it into a char[] or a string. In article <d1k1n8$l0r$1 digitaldaemon.com>, Hytak says...Here is some code that finds a text string in a file. You can use something like this as a starting point. <code> import std.stdio; import std.file; import std.string; int main(char[][] pArg) { char[][] lFileText; int lPos; int lByteNum; struct FileRef { int LineNo; int ByteNo; }; FileRef[] lFound; if (! std.file.exists( pArg[1] )) { writefln("File '%s' not found.", pArg[1]); return 1; } // Read the entire file in and split it into lines. lFileText = std.string.splitlines(cast(char[]) std.file.read(pArg[1])); // Examine each line in turn. There could be multiple hits/line. foreach(int i, char[] lLine; lFileText) { lByteNum = 0; while((lPos = std.string.find(lLine[lByteNum..$], pArg[2])) != -1) { lByteNum += lPos + 1; lFound.length = lFound.length + 1; lFound[$-1].LineNo = i+1; lFound[$-1].ByteNo = lByteNum; } } if (lFound.length == 0) { writefln("File '%s' does not contain '%s'", pArg[1],pArg[2]); return 2; } // Display each occurance. writefln("File '%s' has '%s' at Line:Column ...", pArg[1],pArg[2]); foreach(FileRef lRef; lFound) { writefln("%8d:%d", lRef.LineNo, lRef.ByteNo); } return 0; } </code> -- Derek Parnell Melbourne, Australia 21/03/2005 2:19:17 AMHi I just try few things before starting a little program in D, and I will need to read and write things to a file. I know how to do it in C++ and a little bit in C, but the D's fonctions to read and write to file seems to be a mix of C and C++. What I want to to is to open a .txt and to search in it the word "MYWORRD". Do we have to use getc? What should it look like? I saw the functions read, write, append, ungetc and all but it should be nice someone write a deeper tutorial on them (does it exist?) I saw on http://www.quit-clan.de/docwiki/view.php?pageid=3 that there was some example, nice to look... but now really what I am looking for.
Mar 20 2005
Thanks a lot, it will really help me. In article <zcui0k32ti67$.p1x9mhr2cj8a$.dlg 40tude.net>, Derek Parnell says...On Sun, 20 Mar 2005 15:05:41 +0000 (UTC), Hytak wrote:Well I forgot: what I want to do is to read the word after "MYWORD:" and to store it into a char[] or a string. In article <d1k1n8$l0r$1 digitaldaemon.com>, Hytak says...Here is some code that finds a text string in a file. You can use something like this as a starting point. <code> import std.stdio; import std.file; import std.string; int main(char[][] pArg) { char[][] lFileText; int lPos; int lByteNum; struct FileRef { int LineNo; int ByteNo; }; FileRef[] lFound; if (! std.file.exists( pArg[1] )) { writefln("File '%s' not found.", pArg[1]); return 1; } // Read the entire file in and split it into lines. lFileText = std.string.splitlines(cast(char[]) std.file.read(pArg[1])); // Examine each line in turn. There could be multiple hits/line. foreach(int i, char[] lLine; lFileText) { lByteNum = 0; while((lPos = std.string.find(lLine[lByteNum..$], pArg[2])) != -1) { lByteNum += lPos + 1; lFound.length = lFound.length + 1; lFound[$-1].LineNo = i+1; lFound[$-1].ByteNo = lByteNum; } } if (lFound.length == 0) { writefln("File '%s' does not contain '%s'", pArg[1],pArg[2]); return 2; } // Display each occurance. writefln("File '%s' has '%s' at Line:Column ...", pArg[1],pArg[2]); foreach(FileRef lRef; lFound) { writefln("%8d:%d", lRef.LineNo, lRef.ByteNo); } return 0; } </code> -- Derek Parnell Melbourne, Australia 21/03/2005 2:19:17 AMHi I just try few things before starting a little program in D, and I will need to read and write things to a file. I know how to do it in C++ and a little bit in C, but the D's fonctions to read and write to file seems to be a mix of C and C++. What I want to to is to open a .txt and to search in it the word "MYWORRD". Do we have to use getc? What should it look like? I saw the functions read, write, append, ungetc and all but it should be nice someone write a deeper tutorial on them (does it exist?) I saw on http://www.quit-clan.de/docwiki/view.php?pageid=3 that there was some example, nice to look... but now really what I am looking for.
Mar 20 2005
Derek Parnell says... Very useful and quite nifty code example. My comments are not actually so much directed at you Derek (since you know all that :)), but for folks that may want to expand on the code:struct FileRef { int LineNo; int ByteNo; char[] Line; // Added };I like your using a struct to keep all the infos together. I added a "Line" info to let the user compare search results with the text lines found further down.if (! std.file.exists( pArg[1] )) { writefln("File '%s' not found.", pArg[1]); return 1; }Minor thing. I noted when pArg[2] is empty (not specified on the command line), the code will exit. A check of this case + warning might be a good idea.// Read the entire file in and split it into lines. lFileText = std.string.splitlines(cast(char[]) std.file.read(pArg[1]));Clever cast() to get the read to work as input for splitlines :) General Question: I have now seen the specification of full "lib paths" to funtions in several code fragments. Since "splitlines" is actually a unique lib in std one can probably do without the "std.string.", but in the case of "read" specifying the lib path is probably a good thing since read() can be found in std.file and in std.stream. Question, should one always specify full lib paths? IMO it makes reading the code a bit harder, though it is instructive to know exactly where the code/function is from. Experimenting with alias (totally new to me): alias std.string.splitlines aesplitlines; //works lFileText = aesplitlines( cast(char[]) std.file.read(args[1]) ); also works. Use of alias will probably make code harder to read, since every programmer would start using his own set of aliases. Is it thus frowned on, style-wise, to use alias in such cases? ..lFound[$-1].ByteNo = lByteNum; lFound[$-1].Line = lLine; // Added..writefln("%8d:%d:%s", lRef.LineNo, lRef.ByteNo, lRef.Line); //ChangedAdded the "Line" info, should you like to see it. AEon
Mar 20 2005
Derek,foreach(int i, char[] lLine; lFileText) { lByteNum = 0; while((lPos = std.string.find(lLine[lByteNum..$], args[2])) != -1) { lByteNum += lPos + 1; lFound.length = lFound.length + 1; lFound[$-1].LineNo = i+1; lFound[$-1].ByteNo = lByteNum; lFound[$-1].Line = lLine; } }Forgot to ask about the new notation: AFAICT "lLine[lByteNum..$]" means "lLine[lByteNum..lLine.length]", right? I have looked in the documentation, but have not been able to find anything on $? I thought I read something about $ in the .D forums, but had thought that way still up for discussion, but not actually in D. AEon
Mar 20 2005
On Sun, 20 Mar 2005 18:52:14 +0000 (UTC), AEon <AEon_member pathlink.com> wrote:General Question: I have now seen the specification of full "lib paths" to funtions in several code fragments. Since "splitlines" is actually a unique lib in std one can probably do without the "std.string.", but in the case of "read" specifying the lib path is probably a good thing since read() can be found in std.file and in std.stream. Question, should one always specify full lib paths? IMO it makes reading the code a bit harder, though it is instructive to know exactly where the code/function is from.I think it's a style choice. I agree that it's instructive, but I also agree that it's harder to read. (those are opinions) It's 'required' in the case of "read" because of the ambiguity/collision. I only use it when it's required, or I use an alias as below.Experimenting with alias (totally new to me): alias std.string.splitlines aesplitlines; //works lFileText = aesplitlines( cast(char[]) std.file.read(args[1]) ); also works. Use of alias will probably make code harder to read, since every programmer would start using his own set of aliases. Is it thus frowned on, style-wise, to use alias in such cases?No. The only style guideline WRT to alias is that "Meaningless Type Aliases" should be avoided, things like: alias void VOID; alias int INT; alias int* pint; http://www.digitalmars.com/d/dstyle.html Personally I would use something like: alias std.file.read read; but I would not use: alias std.file.read bob; //or anything other than 'read' because IMO alias is used to shorten the code and make it easier to follow. Changing the name of a well known function to something else makes it harder to follow the code. Though it may be possible to choose another name that makes more sense in a specific context.. even so the programmer looking at your code has to remember them for the duration so too many of them would definately make that harder. Regan
Mar 20 2005
Regan Heath:Personally I would use something like: alias std.file.read read; but I would not use: alias std.file.read bob; //or anything other than 'read' because IMO alias is used to shorten the code and make it easier to follow. Changing the name of a well known function to something else makes it harder to follow the code. ...Ok... does the above alias have some evil side effects (type checking no longer working e.g.), like the #define in C used to do? It's great to be able to ask questions, this way I learn things *a lot* faster. Thanx everyone. AEon
Mar 20 2005
On Sun, 20 Mar 2005 23:05:29 +0000 (UTC), AEon <AEon_member pathlink.com> wrote:Regan Heath:The one above, no, not as far as I can see. Firstly, because it doesn't alias types, and secondly even if it did... http://www.digitalmars.com/d/declaration.html "Type aliases are equivalent to the C typedef." So "alias" is more similar to "typedef" than "define". The biggest reason is that "define" was handled by the pre-processor, effectively doing a find/replace on the source *before* the compiler sees it. http://www.digitalmars.com/d/declaration.html "Aliased types are semantically identical to the types they are aliased to. The debugger cannot distinguish between them, and there is no difference as far as function overloading is concerned. For example: alias int myint; void foo(int x) { . } void foo(myint m) { . }error, multiply defined function foo" So, AIUI "alias" creates a new name for a type, which is treated identically to the old name. "typedef" actually creates a new type. Regards, ReganPersonally I would use something like: alias std.file.read read; but I would not use: alias std.file.read bob; //or anything other than 'read' because IMO alias is used to shorten the code and make it easier to follow. Changing the name of a well known function to something else makes it harder to follow the code. ...Ok... does the above alias have some evil side effects (type checking no longer working e.g.), like the #define in C used to do?
Mar 20 2005
Regan Heath:Personally I would use something like: alias std.file.read read; but I would not use: alias std.file.read bob; //or anything other than 'read' because IMO alias is used to shorten the code and make it easier to follow. Changing the name of a well known function to something else makes it harder to follow the code. ...Ok... does the above alias have some evil side effects (type checking no longer working e.g.), like the #define in C used to do? It's great to be able to ask questions, this way I learn things *a lot* faster. Thanx everyone. AEon
Mar 20 2005
On Sun, 20 Mar 2005 18:52:14 +0000 (UTC), AEon wrote:Derek Parnell says... Very useful and quite nifty code example. My comments are not actually so much directed at you Derek (since you know all that :)), but for folks that may want to expand on the code:LOL. I whipped up this code in ten minutes at 2:20AM so I expect it could have been more polished!I'm a database person and data factoring is second nature to me ;-)struct FileRef { int LineNo; int ByteNo; char[] Line; // Added };I like your using a struct to keep all the infos together. I added a "Line" info to let the user compare search results with the text lines found further down.I didn't bother with an really serious argument checking. In a real application one would improve that situation.if (! std.file.exists( pArg[1] )) { writefln("File '%s' not found.", pArg[1]); return 1; }Minor thing. I noted when pArg[2] is empty (not specified on the command line), the code will exit. A check of this case + warning might be a good idea.I try to. The reason is mainly that if you don't and later on a new module comes into scope with a same-named member, the code suddenly finds a reason to trouble the compiler. (Given that members don't tend to travel to different modules - they settle down very quickly so recoding a package path is not really a bother).// Read the entire file in and split it into lines. lFileText = std.string.splitlines(cast(char[]) std.file.read(pArg[1]));Clever cast() to get the read to work as input for splitlines :) General Question: I have now seen the specification of full "lib paths" to funtions in several code fragments. Since "splitlines" is actually a unique lib in std one can probably do without the "std.string.", but in the case of "read" specifying the lib path is probably a good thing since read() can be found in std.file and in std.stream. Question, should one always specify full lib paths?IMO it makes reading the code a bit harder, though it is instructive to know exactly where the code/function is from.Yes, it does. And yes it is.Experimenting with alias (totally new to me): alias std.string.splitlines aesplitlines; //works lFileText = aesplitlines( cast(char[]) std.file.read(args[1]) ); also works. Use of alias will probably make code harder to read, since every programmer would start using his own set of aliases. Is it thus frowned on, style-wise, to use alias in such cases?A common use of alias is to help readability, as you note. You could have done this too... alias std.string.splitlines splitlines; lFileText = splitlines( cast(char[]) std.file.read(args[1]) ); -- Derek Parnell Melbourne, Australia 21/03/2005 7:12:34 AM
Mar 20 2005