* Text_IO.End_Of_File Problem @ 2001-11-25 22:42 Hambut 2001-11-26 1:53 ` Jeffrey Carter ` (2 more replies) 0 siblings, 3 replies; 11+ messages in thread From: Hambut @ 2001-11-25 22:42 UTC (permalink / raw) Hi, I'm getting an exception with the attached code, and I can't see what I'm doing wrong, or why it's falling over. The code basically: 1. Opens a file (sequential IO) 2. Fills it with a sequence of Ascii.LF's and ASCII.CR's 3. Closes it and reopens it as text_io 4. reads each character in and outputs it's Ascii value to screen. What *seems* to be happening is that text_io.end_of_file is not detecting the end of file properly in this case [or I've made some elementary error (having spent lots of time correcting my errors up to now I know which option my money's on :-)]. I'd appreciate it if someone on here could have a peer at this and give me a pointer as to where I'm going wrong. The output I get from executing the code is: " 13 13 raised ADA.IO_EXCEPTIONS.END_ERROR : a-textio.adb:394 " Thanks in advance for any help. Cheers, Hambut. =====Code Follows====== with Text_Io; with Ada.Sequential_Io; procedure Eof_Fails is package Io is new Ada.Sequential_Io( Character ); Test_File_Name : constant String := "Test_fails"; Sequential_File : Io.File_Type; Text_File : Text_Io.File_Type; Failure_Characters : constant String := ( 1 => Ascii.CR, 2 => Ascii.CR, 3 => Ascii.LF, 4 => Ascii.CR, 5 => Ascii.CR, 6 => Ascii.LF, 7 => Ascii.CR, 8 => Ascii.LF ); -- These seem to work OK. -- Failure_Characters : constant String := ( 1 => Ascii.CR, -- 2 => Ascii.CR, -- 3 => Ascii.LF, -- 4 => Ascii.CR ); C : Character; begin -- First set up the test file -- Io.Create( File => Sequential_File, Name => Test_File_Name ); for I in Failure_Characters'First..Failure_Characters'Last loop Io.Write( File => Sequential_File, Item => Failure_Characters(I) ); end loop; Io.Close( File => Sequential_File ); -- Now try and read in as a text file -- Text_Io.Open( File => Text_File, Mode => Text_Io.In_File, Name => Test_File_Name ); while not Text_Io.End_Of_File( File => Text_File ) loop Text_Io.Get( File => Text_File, Item => C ); Text_Io.Put_Line( Integer'Image( Character'Pos(C))); end loop; Text_Io.Close( File => Text_File ); exception when others => Text_Io.Close( File => Text_File ); raise; end Eof_fails; ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-25 22:42 Text_IO.End_Of_File Problem Hambut @ 2001-11-26 1:53 ` Jeffrey Carter 2001-11-26 12:30 ` Hambut 2001-11-26 13:25 ` Hambut 2001-11-26 2:15 ` Patrick Hohmeyer 2001-11-26 2:35 ` Nick Roberts 2 siblings, 2 replies; 11+ messages in thread From: Jeffrey Carter @ 2001-11-26 1:53 UTC (permalink / raw) Hambut wrote: > > Hi, > > I'm getting an exception with the attached code, and I can't see what > I'm doing wrong, or why it's falling over. It's not falling over, it's terminating with an unhandled exception. > The output I get from executing the code is: > > " > 13 > 13 > > raised ADA.IO_EXCEPTIONS.END_ERROR : a-textio.adb:394 > " > > =====Code Follows====== > > with Text_Io; > with Ada.Sequential_Io; > procedure Eof_Fails is > > package Io is new Ada.Sequential_Io( Character ); > > Test_File_Name : constant String := "Test_fails"; > Sequential_File : Io.File_Type; > Text_File : Text_Io.File_Type; > > Failure_Characters : constant String := ( 1 => Ascii.CR, > 2 => Ascii.CR, > 3 => Ascii.LF, > 4 => Ascii.CR, > 5 => Ascii.CR, > 6 => Ascii.LF, > 7 => Ascii.CR, > 8 => Ascii.LF ); What you are doing is writing characters that contain embedded within them what your specific system considers line terminators. Based on your sample output, I would guess you're running under Win32. On such systems, a line terminator is a CR followed by an LF. So you have (in Text_IO terms) 3 lines. The first 2 lines contain a single character, which is a CR; the 3rd line is null. Next, note how Ada.Text_IO.Get (Character) works. It skips any line terminators looking for a character. So your first call to Get reads item 1 above. The second skips a line terminator (items 2 & 3) and reads item 4. You are not now at the end of the file, so End_Of_File returns False. Your 3rd call to get skips 2 line terminators (items 5-8), which brings you to the end of the file, raising End_Error. Note that on a different system, with (a) different character(s) representing a line terminator, you would get different results, but you could still define a value for Failure_Characters that would cause the program to raise End_Error even though End_Of_File is False. > > -- These seem to work OK. > -- Failure_Characters : constant String := ( 1 => Ascii.CR, > -- 2 => Ascii.CR, > -- 3 => Ascii.LF, > -- 4 => Ascii.CR ); This would work on Win32 because after the 2nd call to Get (which reads item 4), you are at the end of the file, so End_Of_File returns True. > > C : Character; > begin > -- First set up the test file > -- > Io.Create( File => Sequential_File, > Name => Test_File_Name ); > > for I in Failure_Characters'First..Failure_Characters'Last loop Note that X'First .. X'Last is equivalent to X'range, which is clearer. > Io.Write( File => Sequential_File, > Item => Failure_Characters(I) ); > end loop; > > Io.Close( File => Sequential_File ); > > -- Now try and read in as a text file > -- > Text_Io.Open( File => Text_File, > Mode => Text_Io.In_File, > Name => Test_File_Name ); > > while not Text_Io.End_Of_File( File => Text_File ) loop > Text_Io.Get( File => Text_File, > Item => C ); > Text_Io.Put_Line( Integer'Image( Character'Pos(C))); > end loop; > > Text_Io.Close( File => Text_File ); > exception > when others => > Text_Io.Close( File => Text_File ); > raise; > end Eof_fails; The basic lesson is that Text_IO interprets the characters in your file, and in the process does not return every character to you. This can result in some operations reading past the end of the file, although End_Of_File has just returned False. -- Jeff Carter "We call your door-opening request a silly thing." Monty Python & the Holy Grail ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-26 1:53 ` Jeffrey Carter @ 2001-11-26 12:30 ` Hambut 2001-11-26 16:50 ` Mark Biggar 2001-11-26 13:25 ` Hambut 1 sibling, 1 reply; 11+ messages in thread From: Hambut @ 2001-11-26 12:30 UTC (permalink / raw) First apologies - I should have specified that I was working on Wondows with Gnat 3.13p. Jeffrey Carter <jrcarter@acm.org> wrote in message news:<3C01A0AA.AF2F54BF@acm.org>... > Hambut wrote: > > > > Hi, > > > > I'm getting an exception with the attached code, and I can't see what > > I'm doing wrong, or why it's falling over. > > It's not falling over, it's terminating with an unhandled exception. Well - I do handle it, I just purposely raise it again so I can see the exception :-). > > > > Failure_Characters : constant String := ( 1 => Ascii.CR, > > 2 => Ascii.CR, > > 3 => Ascii.LF, > > 4 => Ascii.CR, > > 5 => Ascii.CR, > > 6 => Ascii.LF, > > 7 => Ascii.CR, > > 8 => Ascii.LF ); > > What you are doing is writing characters that contain embedded within > them what your specific system considers line terminators. Based on your > sample output, I would guess you're running under Win32. On such > systems, a line terminator is a CR followed by an LF. So you have (in > Text_IO terms) 3 lines. The first 2 lines contain a single character, > which is a CR; the 3rd line is null. Perhaps this is a part of my problem - Reading the secret documents, and looking at a-textio.ads I noted that LM (Line marker?) was set to Ascii.LF. I should have spent more time looking for windows specific docs perhaps? > > Next, note how Ada.Text_IO.Get (Character) works. It skips any line > terminators looking for a character. So your first call to Get reads > item 1 above. The second skips a line terminator (items 2 & 3) and reads > item 4. You are not now at the end of the file, so End_Of_File returns > False. Your 3rd call to get skips 2 line terminators (items 5-8), which > brings you to the end of the file, raising End_Error. > > Note that on a different system, with (a) different character(s) > representing a line terminator, you would get different results, but you > could still define a value for Failure_Characters that would cause the > program to raise End_Error even though End_Of_File is False. > Hmm - OK I understand what you're saying. I think my naive(?) view was that End_of_File would return true when there were no more characters for Get to return. To me this seems like an intuitive assumption. > > The basic lesson is that Text_IO interprets the characters in your file, > and in the process does not return every character to you. This can > result in some operations reading past the end of the file, although > End_Of_File has just returned False. This seems counter-intuitive. However assuming that it is in line with the LRM I guess it must be OK. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-26 12:30 ` Hambut @ 2001-11-26 16:50 ` Mark Biggar 0 siblings, 0 replies; 11+ messages in thread From: Mark Biggar @ 2001-11-26 16:50 UTC (permalink / raw) Hambut wrote: > > Hmm - OK I understand what you're saying. I think my naive(?) view > was that End_of_File would return true when there were no more > characters for Get to return. To me this seems like an intuitive > assumption. It may be intuitive, but that assumption requires arbitrarily far look ahead. Consider a large file containing a single character followed by 1,000,000+ line terminators. Your assumption requires reading the whole file on encountering the first line terminator. -- Mark Biggar mark.a.biggar@home.com ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-26 1:53 ` Jeffrey Carter 2001-11-26 12:30 ` Hambut @ 2001-11-26 13:25 ` Hambut 1 sibling, 0 replies; 11+ messages in thread From: Hambut @ 2001-11-26 13:25 UTC (permalink / raw) Jeffrey Carter <jrcarter@acm.org> wrote in message news:<3C01A0AA.AF2F54BF@acm.org>... <snip> In an earlier reply I said that I thought the way that end_of_file works seemed non-intuitive. Well after a little thought it doesn't seem so non-intuitive now. So please disregard those comments. I was mixing end_of_file with an imaginary 'end_of_characters_for_get_to_return' function. I think there was a cognitive error in my thoughts at the time..... ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-25 22:42 Text_IO.End_Of_File Problem Hambut 2001-11-26 1:53 ` Jeffrey Carter @ 2001-11-26 2:15 ` Patrick Hohmeyer 2001-11-26 12:36 ` Hambut 2001-11-26 2:35 ` Nick Roberts 2 siblings, 1 reply; 11+ messages in thread From: Patrick Hohmeyer @ 2001-11-26 2:15 UTC (permalink / raw) Hambut wrote : > Hi, > > I'm getting an exception with the attached code, and I can't see what > I'm doing wrong, or why it's falling over. > > The code basically: > > 1. Opens a file (sequential IO) > 2. Fills it with a sequence of Ascii.LF's and ASCII.CR's > 3. Closes it and reopens it as text_io > 4. reads each character in and outputs it's Ascii value to screen. > <re-arangement> > Failure_Characters : constant String := ( 1 => Ascii.CR, > 2 => Ascii.CR, > 3 => Ascii.LF, > 4 => Ascii.CR, > 5 => Ascii.CR, > 6 => Ascii.LF, > 7 => Ascii.CR, > 8 => Ascii.LF ); In Ada.Text_IO an end_of_line equals CR LF (as in windows) So your file reads : CR, end_of_line, CR, end_of_line, end_of_line > What *seems* to be happening is that text_io.end_of_file is not > detecting the end of file properly in this case [or I've made some > elementary error (having spent lots of time correcting my errors up to > now I know which option my money's on :-)]. Get (Item : Character) skips all end_of_line's (and all end_of_page) and reads the first "normal" character. But end_of_file just tests the next character, so when the last character of your file is an end_of_line, an EOF test doesn't prevent Get (Item : Character) to skip the last end_of_line and depass the EOF. To get rid of this you must test for an end_of_line and when you encounter one, skip it with Skip_Line. Does this pointer helps, or do you want a corrected code? -- Patrick Hohmeyer ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-26 2:15 ` Patrick Hohmeyer @ 2001-11-26 12:36 ` Hambut 0 siblings, 0 replies; 11+ messages in thread From: Hambut @ 2001-11-26 12:36 UTC (permalink / raw) Patrick Hohmeyer <pi3_1415926536@yahoo.ca> wrote in message news:<uahM7.2663$3i2.402543@news20.bellglobal.com>... <snip> > To get rid of this you must test for an end_of_line and > when you encounter one, skip it with Skip_Line. > Does this mean I need to do something like: 1. Test for end_of_line 2. If true then repeatedly skip_line and test for end_of_line until it's false 3. Test for end_of_file?? Hmm doesn't seem to work too well.. Perhaps it needs a repeated test for end_of_file in 2 when end_of_line is true. > Does this pointer helps, or do you want a corrected code? It might help. Cheers for the reply. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-25 22:42 Text_IO.End_Of_File Problem Hambut 2001-11-26 1:53 ` Jeffrey Carter 2001-11-26 2:15 ` Patrick Hohmeyer @ 2001-11-26 2:35 ` Nick Roberts 2001-11-26 12:13 ` Hambut 2 siblings, 1 reply; 11+ messages in thread From: Nick Roberts @ 2001-11-26 2:35 UTC (permalink / raw) Hambut, the basic answer is: you cannot mix Ada.Sequential_IO and Ada.Text_IO! The format in which Sequential_IO writes data is implementation-dependent, and may not even vaguely correspond to anything that Text_IO can read back. I have two questions for you: (1) WHY were you trying to write with Sequential_IO and then read with Text_IO? (2) WHAT do you really want to do? I will help you with (2) if I can (and if you require). -- Best wishes, Nick Roberts ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-26 2:35 ` Nick Roberts @ 2001-11-26 12:13 ` Hambut 2001-11-26 18:00 ` Nick Roberts 0 siblings, 1 reply; 11+ messages in thread From: Hambut @ 2001-11-26 12:13 UTC (permalink / raw) "Nick Roberts" <nickroberts@adaos.worldonline.co.uk> wrote in message news:<9tsbca$4g95n$1@ID-25716.news.dfncis.de>... > Hambut, the basic answer is: you cannot mix Ada.Sequential_IO and > Ada.Text_IO! The format in which Sequential_IO writes data is > implementation-dependent, and may not even vaguely correspond to anything > that Text_IO can read back. I appreciate this. the reason I mixed the two was to get a small self-contained program to demonstrate my problem. The actual app uses text_io to set the file up, and text_io to read the file. However doing this I managed to get an exception to occur where I didn't expect one. Hence the query. > > I have two questions for you: > > (1) WHY were you trying to write with Sequential_IO and then read with > Text_IO? See above. > > (2) WHAT do you really want to do? > What I really want to do is fairly trivial really (or at least should be), and involves downloading an email, writing it into a file, and then parsing the email to extract attachments etc. Currently I'm downloading the email and saving it into a temporary file, and then later opening it to pull out the attachment. Perhaps my real problem is using text_io to write POP3-type output straight to a file (it adds a load of superfluous line ends I guess), in which case Sequential_IO looks more hopeful. > I will help you with (2) if I can (and if you require). I'm hoping I won't need help with this, but you're offer is much appreciated. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-26 12:13 ` Hambut @ 2001-11-26 18:00 ` Nick Roberts 2001-11-27 9:51 ` Hambut 0 siblings, 1 reply; 11+ messages in thread From: Nick Roberts @ 2001-11-26 18:00 UTC (permalink / raw) Sequential_IO is definitely not what you require. What I need to know now is how you are getting text from your POP3 server. If you are able to read text lines from the server, like this: Text: String(1..1024); -- arbitrary length Last: Natural; ... Get_Line(Server,Text,Last); with the line ends (almost certainly CRLFs) dealt with correctly, you should have no trouble transferring to a text file, e.g.: loop if End_of_File(Server) then -- deal with premature termination end if; -- or catch End_Error Get_Line(Server,Text,Last); exit when Last=1 and Text(1)='.'; Put_Line(Temp,Text(1..Last)); end loop; regardless of how many blank lines there may be. Of course this must be preceded and followed by code that sends the right commands to the server (I forget the commands now, I'm stretching my memory back 10 years as it is ;-) and interprets its response codes. Don't forget to close or reset the Temp file. E.g.: Close(Temp); -- after writing to it ... Open(Temp,In_File,Temp_Name); -- now process it for attachments If your code is just getting TCP segments (rather than whole lines), I suggest you need a buffer task to deliver actual lines to your main code. When you come to writing out the attachments, for those which produce binary data you will need to use Ada.Streams.Stream_IO to write out the binary data. Happy to give more detail on any point, if you require. Does any of this help you? -- Best wishes, Nick Roberts > > (2) WHAT do you really want to do? > > > > What I really want to do is fairly trivial really (or at least should > be), and involves downloading an email, writing it into a file, and > then parsing the email to extract attachments etc. Currently I'm > downloading the email and saving it into a temporary file, and then > later opening it to pull out the attachment. Perhaps my real problem > is using text_io to write POP3-type output straight to a file (it adds > a load of superfluous line ends I guess), in which case Sequential_IO > looks more hopeful. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Text_IO.End_Of_File Problem 2001-11-26 18:00 ` Nick Roberts @ 2001-11-27 9:51 ` Hambut 0 siblings, 0 replies; 11+ messages in thread From: Hambut @ 2001-11-27 9:51 UTC (permalink / raw) "Nick Roberts" <nickroberts@adaos.worldonline.co.uk> wrote in message news:<9tu05r$4ua5t$1@ID-25716.news.dfncis.de>... > Sequential_IO is definitely not what you require. Perhaps not. It seemed attractive because it doesn't add line ends in, which would mean that I wouldn't have to strip off the 'CRLF's returned from the server. Basically laziness on my part. I assume you're definitely against the use of sequential_io in this case is because there's no guarantee (within the standard?) that text_io would be able to sensibly read it back. Which seems sensible in general. Cheers for the help. I'll no doubt be back with other daft questions. <snip> > > When you come to writing out the attachments, for those which produce binary > data you will need to use Ada.Streams.Stream_IO to write out the binary > data. > A good point. cheers, Hambut ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2001-11-27 9:51 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2001-11-25 22:42 Text_IO.End_Of_File Problem Hambut 2001-11-26 1:53 ` Jeffrey Carter 2001-11-26 12:30 ` Hambut 2001-11-26 16:50 ` Mark Biggar 2001-11-26 13:25 ` Hambut 2001-11-26 2:15 ` Patrick Hohmeyer 2001-11-26 12:36 ` Hambut 2001-11-26 2:35 ` Nick Roberts 2001-11-26 12:13 ` Hambut 2001-11-26 18:00 ` Nick Roberts 2001-11-27 9:51 ` Hambut
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox