I've stumbled on a strange behavior while trying to use custom terminators for ReadString
.
When I use a simple String
as the terminator, I get the following behavior
stream = StringToStream[" abc def g\n hi"]
Do[{
StreamPosition[stream],
ReadString[stream, StringExpression[" "] // FullForm,
StreamPosition[stream]
} // Print
, {6}]
(*
{0, "abc", 4}
{4, "def", 9}
{9, "g\n", 12}
{12, "hi", 16}
{16, EndOfFile, 16}
{16, EndOfFile, 16}
*)
Everything OK here. It looks as the default is to discard empy "reads". If I use, instead, a simple Alternative
things behave very differently.
stream = StringToStream[" abc def g\n hi"]
Do[{
StreamPosition[stream],
ReadString[stream, StringExpression[" " | EndOfString]] // FullForm,
StreamPosition[stream]
}
, {9}]
(*
{0, "", 16}
{16, "abc", 16}
{16, "", 16}
{16, "def", 16}
{16, "g\n", 16}
{16, "", 16}
{16, "hi", 16}
{16, EndOfFile, 16}
{16, EndOfFile, 16}
*)
Not only empty records are now presented, but the StreamPosition
mechanism becomes useless.
I suppose the string is being read in it's entirety on the second example, but why? There is no ambiguity in the separator, and no need for look-aheads if the parser matches a single " "
.
And is there a reason for empty records to be returned by default only on the second example?
Read[strm, Word, 1]
but alsoRead[strm, WhitespaceSequence, 1]
.ReadString[strm, Except[WhitespaceCharacter]
seemed like a good solution to me, however MMA does not like this kind of string pattern inReadString
. $\endgroup$ReadString[strm, StringExpression[Except[WhitespaceCharacter]]
works, if you're willing to accept the idiosyncrasies I've pointed above! $\endgroup$ReadString
could also return the terminator... I think, part of the problem is constantly setting the stream position. $\endgroup$StreamPosition
s, that you show in the example output, but rather suffers from the same problem as the second example. $\endgroup$