I have a need to write a character to a text file. Currently I am writing the file using a streamwriter and I have tried everything I can imagine, but I cannot get a single character "°" to write to the file properly. If I put it as a bit of text it is converted to "°" and this causes additional problems when the data has to be re-evaluated with another program.
I tried writing it as a string initially, then I tried writing it as a character, but regardless, each time it turns out the same.
That depends what encoding you are using, and in what context the problem occurs. For example most .Net text file tools uses Utf8 encoding by default, so if I for instance if I copy the char you posted and write it to a text file I can also read it back or view it in Notepad without problems. You have to explain some more and post some relevant code methinks.
This is a relatively simple file writing function that takes a string() and writes each line out to a file.
The strings, built within code is something similar to this:
"01-28-2010,12:11:38,N 38°51'41.0616",W 94°49'38.9712",0.5mph,253.2°,983ft"
Everything works great, with the exception of the writing portion. It outputs the data as:
"01-28-2010,12:11:38,N 38°51'41.0616",W 94°49'38.9712",0.5mph,253.2°,983ft"
As you can see there are added characters in the string.
VB.NET:
Public Shared Function WriteToFile(ByVal FileName As String, ByVal lines() As String) As Boolean
Try
Dim sw As New System.IO.StreamWriter(FileName)
Dim X As Integer = 1
Do While X <= UBound(lines)
sw.Write(lines(X))
X += 1
Loop
sw.Close()
Return True
Catch ex As Exception
Return False
End Try
End Function
I have checked to see if perhaps I was not creating the string properly, and each time I received similar results. I have tried these various permutations in the event there was something amis in the string building:
Finally I resorted to writing the lines as binary and got similar results, but with the added problem that every character is now prepended with hex 01.
I suppose I could run the entire string through a single character byte and write that single byte out to the file, but that is so inefficient.
I have also used every encoding option available and still no dice
Also, when viewing the file with notepad, the error isn't evident, it is only when processing the file contents with another program that I became aware of the issue.
If you view the files in VIM or with a binary viewer, you can see the additional characters.
The problem with using utf7 is the character is still not written correctly. A sample using utf7 is:
"01-29-2010,20:23:28,N 38+ALA-51'40.8420+ACI-,W 94+ALA-49'42.1356+ACI-,2.4mph,0.0+ALA-,823ft"
Other formats produce similar results, some formats produce a result that appears to be correct, but when read, the additional bytes appear. Notepad is especially egregious when it comes to ignoring characters, VIM is better, but even it will ignore characters if the file type characters are set at the beginning of the file.
I guess I will have to convert everything to a byte and use a binarywriter to write each byte to the file individually .. not the solution I would have hoped for, but it should work ... at least the last time I used a binarywriter to write a byte to a file, it would write it as the byte you sent and not expand it to some unknown format.
There is nothing unknown about the bytes a StreamWriter writes for text, it's all about the encoding used. Whether you convert text to bytes using the specified encoding or you write text with StreamWriter using the same specified encoding produce exactly the same result. The only difference using StreamWriter is that it adds the byte-order-mark at start of file specifying the encoding used, but the byte content of the text if identical.
you are right, thats why I have to use a binarywriter instead of a streamwriter ... streamwriter is flaky and doesn't interpret characters correctly, regardless of format used ... chr(176) should produce a binary B0 when using at least one of the streamwriter formats, but there isn't one that will do it.
I had to convert each character to a single byte and write that byte out to a binarywriter stream
anyway, i am now getting what I needed using the following code:
VB.NET:
Public Shared Function WriteToFile(ByVal FileName As String, ByVal lines() As String) As Boolean
Try
Dim sw As New System.IO.FileStream(FileName, IO.FileMode.Create)
Dim bw As New System.IO.BinaryWriter(sw)
Dim X As Integer = 1
Dim Y As Integer
Dim Byt As Byte
Do While X <= UBound(lines)
Y = 0
Do While Y < lines(X).Length
Byt = Asc(lines(X).Substring(Y, 1))
bw.Write(Byt)
Y += 1
Loop
Byt = Asc(vbCr)
bw.Write(Byt)
Byt = Asc(vbLf)
bw.Write(Byt)
X += 1
Loop
bw.Close()
sw.Close()
Return True
Catch ex As Exception
Return False
End Try
End Function
Incidently, even a binarywriter does not interpret Chr(10) and Chr(13) correctly, they are written as 2 byte characters ... go figure .. have to expressly convert to a byte to get the proper CrLf as needed.
Rubbish. What you fail to realize is that ALL text is represented with an encoding, the problem you face is finding the right encoding to use, and that includes what encoding used when reading/constructing the source text. So what information do you have? In last post you seem to indicate that the text encoding you require must use one byte only each character. That limits the encodings available, mostly to legacy Ansi codepages. Ascii would have fitted if it were not for the char you initially posted is out of its range, it is one of the "extended ascii" chars and thus available in extended charsets. Two options could be the partially overlapping ISO-8859-1/Windows-1252 8bit encodings. The character "°" has value 176 (or "B0" when referring to the hexadecimal string representation of the byte value). Any 8bit encoding supporting this value will give the 176 byte value. If you used Utf32 which is a 32bit fixed encoding you would get bytes (176,0,0,0), Unicode is variable 1-2 16bit values (176,0) for this char, Utf8 is variable 1-4 bytes and uses bytes (194,176) for this char (thus the "°" when converted back to a 8bit encoding that supports the range of those code points). So try the 8bit encodings I mentioned or look into other possible Ansi encodings, use Encoding.GetEncoding where you either specify the string name or the integer code page to get a compatible Encoding object. Either way I recommend you do some basic research in general about text encoding to expand the current understanding of the topic.
I am not interested in a pissing match, I am merely trying to find the simplest way to resolve the situation.
In notepad, I can create ° by holding [ALT] and entering 0176 .. and when I view it as a binary file, it is simply B0h, there aren't any additional binary values prepending or appending it. That is what I need ... the current ANSI codepage (i.e. Encoding.Default)
Regardless of what encoding format I use when using StreamWriter, the result is always is unacceptible.
Now the only one left is Default, but that uses the OS current ANSI codepage, so if I deploy this application across different languages or perhaps different OS's the result won't be reliable .. or am I wrong to think that?
You are mixing the concepts of text encoding and BOM/preamble here. The former is how the text is represented as bytes (such as the various sample byte values I posted representing the ° char, the same you posted as hex strings now), the latter is the 2-4 bytes signature written to start of file to "explain" the encoding used to any understanding reader (while some readers can't handle BOMs). See for example Byte order mark - Wikipedia, the free encyclopedia To avoid BOM with a custom encoding you must avoid StreamWriter. Just convert the text using the appropriate encoding and write the bytes to file yourself. As said, encoding you cannot avoid, all text is encoded and has a byte representation, it's only a matter of chosing the correct encoding as per requirements.
You can use ANY encoding known that is supported by the current OS, I've already explained how in previous post. Those preset Encoding objects are there just for simplification because they are most used in .Net programming.
So, this sample code lay it out one thing at a time; the string, the encoding, the byte conversion, the file write.
VB.NET:
Dim s As String = "999EW°"
Dim en As System.Text.Encoding = System.Text.Encoding.GetEncoding(1258)
Dim b() As Byte = en.GetBytes(s)
IO.File.WriteAllBytes("filepath", b)
or as I tend to do, skipping code lines that serve no purpose:
I had none of the like in mind, and have no idea how you could perceive anything in this thread as such. I have only tried to explain basic text encoding concepts. Without knowledge and understanding how can problems be solved? I do see your outbursts of frustration only as that, and know you only want to get to the finish line, but I also cannot give complete answers until the problem is properly explained. Sometimes only general advice can be given that you have to apply to specific problem solving yourself. Sometimes general advice is given until more specific help is requested.
Btw, the hex "3F" you got with Ascii is, if you care to know, the byte value 63 (? char), that is substituted according to documentation for character values outside the Ascii encoding range.
please forgive my frustrations .. sometimes intent is missed in a typed medium.
You are correct, the idea in a nutshell is A-->B ... and unfortunately I seem to have reached a point where that doesn't seem possible with StreamWriter, at least not for the purposes I have at hand.
The file will be viewed by humans only rarely, and then only to selectively pick data, so the rendering of it in whatever text reader the person chooses is of little importance, and is in fact of no consequence. The way I see it and understand the way the files are interpreted is that the BOM/Preamble tells notepad/vim/etc... how to render the text.
The fact that the BOM/Preamble is there is unacceptible because the output will be subsequently read by another program (which I have no control over) and extraneous bytes used to depict a specific ANSI codepage or encoding will cause the destination program to crash and burn ... so, obviously I can't use StreamWriter, because in the various encoding formats that don't use a BOM/preamble, the output for char B0h is not B0h, but either a replacement char 3Fh or a multi-byte char, either one of which will cause the destination program to crash.
Given those requirements, I think I am relegated to using a BinaryWriter and writing each byte individually ... unless you see another alternative ...
I was hoping to use a more efficient method because I have to process thousands of files, reading the file data into a buffer, reorganize it into the required format, and write it out to a plain text file (without all the other stuff I have been trying to avoid). Each of these files will have as many as 86,400 records, so we are talking about tens of millions of records that must be processed.
Anyway, the binarywriter provides the correct output, it is just slower than I would like it to be.
File.WriteAllBytes/FileStream/BinaryWriter is the same when you only write bytes to file. Given the size collecting everything in memory, decoding once, and WriteAllBytes would perhaps be less attractive memorywise than writing out parts, while it would be faster. Consider some tens of megabytes of data in memory temporarily during processing is something any modern computer with a GB of ram will easily handle. Writing single bytes for each write call would be rather stupid and time consuming, at the least you would be outputting byte arrays of some size each IO operation. Also, if you're building up large strings with string concats that is incredibly slow compared to for example using a StringBuilder. Two text encoding calls would presumably be slower than one, even if that one encodes twice the amount of text. You can write various code paths and see how they compare in processing time using the Stopwatch class, then make a decision on what balance to make regarding memory use, string building, encoding and IO operations.
I'll work on speed improvements and see what I can do to gain some ground.
I initially thought about utilizing concurrent operations, but considering the IO operations will be the slow link, doing both at the same time would likely create additional speed issues.
You are right, the files are no larger than 2mb, so memory isn't a huge issue.
The general flow of the program is as follows:
while not EOF read lines from oldfile into buffer()
for each line in buffer()
split line into data()
run calculations on data()
reorganize data() into output()
write output() to newfile
process next file
There isn't really alot of room for speed enhancements except on IO operations and I have already had to issue a break in the loop to process application events, otherwise the program appears to hang, even though it hasn't.
Anyway, as I said before, I'll gladly entertain any speed enhancements you can think of.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.