I've read a lot of stuff both on stackoverflow and around the net, I've also tried a dozen variations in my code & am yet to find a solution. The method has to write out a text file according to these file specs I was given, so that another application on a windows based system can import the file. Have discovered a test for this is that if the line breaks look correct in notepad then the import succeeds.
After the file is written to the server, it is then read again passed into a byte array that is later on attached to an email etc. (not sure it this would be relevant)
I started with the higher level classes I usually use to write out files, and as I read more on the subject, tried using FileOutputStream so I could specify the CRLF bytes explicitly. (Still doesn't align correctly in notepad which is the test I'm using)
byte[] CRLF = { 0x0D, 0x0D, 0x0A };//"If you write \r\n on Windows, you'll actually get 0x0D 0x0D 0x0A in the file"
Map<String, ByteBuffer> fileMap = new HashMap<String, ByteBuffer>();
//eg: BA20110627-2.TXT
Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
DateFormat df = new SimpleDateFormat("yyyyMMdd");
String date = df.format(nowTimestamp);
int count = 1;
for(Map<String, List<String>> fileLineListsAndTotAmountMap : fileLineListsAndTotAmountMaps){
String fileName = "BA"+date+"-"+count+".TXT";
FileOutputStream out = new FileOutputStream(f开发者_开发知识库ileStorePath+fileName);
String header = ""+new Header(date).toString();
byte[] headerAsBytes = header.getBytes();
out.write(headerAsBytes);
out.write(CRLF);
//each map only has one entry
Map.Entry<String, List<String>> entry = (Entry<String, List<String>>) fileLineListsAndTotAmountMap.entrySet().toArray()[0];
for(String s: entry.getValue()){
if (!s.equals("")) {
String line = s;
byte[] lineAsBytes = line.getBytes();
out.write(lineAsBytes);
out.write(CRLF);
}
}
//totNumOfDebitRecords, totAmountForDebitRecords
String footer = ""+new Footer(new Integer(fileLineListsAndTotAmountMap.size()).toString(), entry.getKey());
byte[] footerAsBytes = footer.getBytes();
out.write(footerAsBytes);
out.write(CRLF);
out.flush();
out.close();
fileMap.put(fileName, ByteBuffer.wrap(getBytesFromFile(new File(fileStorePath+fileName))));
}
The only other thing I can think of trying is using maybe java.nio.charset.CharsetEncoder & trying to encode it as ASCII though I can't really see how that would help.
Can anyone shed a little more light on this sort of issue?
I haven't read the rest of your code yet, but this is already inaccurate:
//"If you write \r\n on Windows, you'll actually get 0x0D 0x0D 0x0A in the file"
byte[] CRLF = { 0x0D, 0x0D, 0x0A };
CRLF is just 0x0d, 0x0a...
Additional problems:
- You're using
String.getBytes()
without specifying an encoding: almost always a bad idea - You're not using
finally
blocks for your streams - You're using
""+x
to convert a value to a string - just calltoString
(in the case ofheader
you've already got a string);""+x
will work, but it's ugly code - it talks about concatenation, which isn't what you're trying to achieve. - You should use a
Writer
(e.g.OutputStreamWriter
) to write text data - that's what it's there for. Then you don't need to worry about the bytes, you can just work in terms of strings. I would strongly suggestOutputStreamWriter
instead ofFileWriter
so that you can specify the encoding.
Once you've fixed all that, your code will be in a better position to fix the specific problem of line breaks... although I'd strongly recommend that if you're still having problems, you ask a question with a short but complete program which just prints a few lines of text. The header, footer etc are irrelevant to the business of "writing a line separator".
You may well find that the IO-related classes in Guava make all of this easier, too...
System.getProperty("line.separator") returns a String of the OS's newline chars so this should return "\n" for linux and "\r\n" for Windows and so on. Maybe it helps.
精彩评论