我有一個Linux服務器和許多操作系統的客戶端。服務器從客戶端獲取輸入文件。 Linux有行尾char LF,而Mac有行尾char CR,並且 Windows有行尾char CR + LF如何規範Java中的EOL字符?
服務器需要結束行char LF。使用java,我想確保該文件將始終使用linux eol char LF。我怎樣才能實現它?
我有一個Linux服務器和許多操作系統的客戶端。服務器從客戶端獲取輸入文件。 Linux有行尾char LF,而Mac有行尾char CR,並且 Windows有行尾char CR + LF如何規範Java中的EOL字符?
服務器需要結束行char LF。使用java,我想確保該文件將始終使用linux eol char LF。我怎樣才能實現它?
結合兩個答案(由面貌& eumiro):
編輯:閱讀評論之後。線。 System.getProperty(「line.separator」)沒有用處。
之前的文件發送到服務器,打開它替換所有的EOLS和回寫
確保使用數據流這樣做,並在二進制
String fileString;
//..
//read from the file
//..
//for windows
fileString = fileString.replaceAll("\\r\\n", "\n");
fileString = fileString.replaceAll("\\r", "\n");
//..
//write to file in binary mode.. something like:
DataOutputStream os = new DataOutputStream(new FileOutputStream("fname.txt"));
os.write(fileString.getBytes());
//..
//send file
//..
的的replaceAll方法有兩個參數,第一個寫一個是要替換的字符串,另一個是替換字符串。但是,第一個被視爲一個正則表達式,所以'\'就是這樣解釋的。所以:
"\\r\\n" is converted to "\r\n" by Regex
"\r\n" is converted to CR+LR by java
必須爲最近的項目做到這一點。下面的方法會將給定文件中的行尾標準化爲由JVM運行的操作系統指定的行。因此,如果您的JVM在Linux上運行,則會將所有行尾標準化爲LF(\ n)。
由於使用了緩衝流,所以也適用於非常大的文件。
public static void normalizeFile(File f) {
File temp = null;
BufferedReader bufferIn = null;
BufferedWriter bufferOut = null;
try {
if(f.exists()) {
// Create a new temp file to write to
temp = new File(f.getAbsolutePath() + ".normalized");
temp.createNewFile();
// Get a stream to read from the file un-normalized file
FileInputStream fileIn = new FileInputStream(f);
DataInputStream dataIn = new DataInputStream(fileIn);
bufferIn = new BufferedReader(new InputStreamReader(dataIn));
// Get a stream to write to the normalized file
FileOutputStream fileOut = new FileOutputStream(temp);
DataOutputStream dataOut = new DataOutputStream(fileOut);
bufferOut = new BufferedWriter(new OutputStreamWriter(dataOut));
// For each line in the un-normalized file
String line;
while ((line = bufferIn.readLine()) != null) {
// Write the original line plus the operating-system dependent newline
bufferOut.write(line);
bufferOut.newLine();
}
bufferIn.close();
bufferOut.close();
// Remove the original file
f.delete();
// And rename the original file to the new one
temp.renameTo(f);
} else {
// If the file doesn't exist...
log.warn("Could not find file to open: " + f.getAbsolutePath());
}
} catch (Exception e) {
log.warn(e.getMessage(), e);
} finally {
// Clean up, temp should never exist
FileUtils.deleteQuietly(temp);
IOUtils.closeQuietly(bufferIn);
IOUtils.closeQuietly(bufferOut);
}
}
這裏是一個全面的幫助類來處理EOL問題。它部分基於tyjen公佈的解決方案。
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
/**
* Helper class to deal with end-of-line markers in text files.
*
* Loosely based on these examples:
* - http://stackoverflow.com/a/9456947/1084488 (cc by-sa 3.0)
* - http://svn.apache.org/repos/asf/tomcat/trunk/java/org/apache/tomcat/buildutil/CheckEol.java (Apache License v2.0)
*
* This file is posted here to meet the "ShareAlike" requirement of cc by-sa 3.0:
* http://stackoverflow.com/a/27930311/1084488
*
* @author Matthias Stevens
*/
public class EOLUtils
{
/**
* Unix-style end-of-line marker (LF)
*/
private static final String EOL_UNIX = "\n";
/**
* Windows-style end-of-line marker (CRLF)
*/
private static final String EOL_WINDOWS = "\r\n";
/**
* "Old Mac"-style end-of-line marker (CR)
*/
private static final String EOL_OLD_MAC = "\r";
/**
* Default end-of-line marker on current system
*/
private static final String EOL_SYSTEM_DEFAULT = System.getProperty("line.separator");
/**
* The support end-of-line marker modes
*/
public static enum Mode
{
/**
* Unix-style end-of-line marker ("\n")
*/
LF,
/**
* Windows-style end-of-line marker ("\r\n")
*/
CRLF,
/**
* "Old Mac"-style end-of-line marker ("\r")
*/
CR
}
/**
* The default end-of-line marker mode for the current system
*/
public static final Mode SYSTEM_DEFAULT = (EOL_SYSTEM_DEFAULT.equals(EOL_UNIX) ? Mode.LF : (EOL_SYSTEM_DEFAULT
.equals(EOL_WINDOWS) ? Mode.CRLF : (EOL_SYSTEM_DEFAULT.equals(EOL_OLD_MAC) ? Mode.CR : null)));
static
{
// Just in case...
if (SYSTEM_DEFAULT == null)
{
throw new IllegalStateException("Could not determine system default end-of-line marker");
}
}
/**
* Determines the end-of-line {@link Mode} of a text file.
*
* @param textFile the file to investigate
* @return the end-of-line {@link Mode} of the given file, or {@code null} if it could not be determined
* @throws Exception
*/
public static Mode determineEOL(File textFile)
throws Exception
{
if (!textFile.exists())
{
throw new IOException("Could not find file to open: " + textFile.getAbsolutePath());
}
FileInputStream fileIn = new FileInputStream(textFile);
BufferedInputStream bufferIn = new BufferedInputStream(fileIn);
try
{
int prev = -1;
int ch;
while ((ch = bufferIn.read()) != -1)
{
if (ch == '\n')
{
if (prev == '\r')
{
return Mode.CRLF;
}
else
{
return Mode.LF;
}
}
else if (prev == '\r')
{
return Mode.CR;
}
prev = ch;
}
throw new Exception("Could not determine end-of-line marker mode");
}
catch (IOException ioe)
{
throw new Exception("Could not determine end-of-line marker mode", ioe);
}
finally
{
// Clean up:
IOUtils.closeQuietly(bufferIn);
}
}
/**
* Checks whether the given text file has Windows-style (CRLF) line endings.
*
* @param textFile the file to investigate
* @return
* @throws Exception
*/
public static boolean hasWindowsEOL(File textFile)
throws Exception
{
return Mode.CRLF.equals(determineEOL(textFile));
}
/**
* Checks whether the given text file has Unix-style (LF) line endings.
*
* @param textFile the file to investigate
* @return
* @throws Exception
*/
public static boolean hasUnixEOL(File textFile)
throws Exception
{
return Mode.LF.equals(determineEOL(textFile));
}
/**
* Checks whether the given text file has "Old Mac"-style (CR) line endings.
*
* @param textFile the file to investigate
* @return
* @throws Exception
*/
public static boolean hasOldMacEOL(File textFile)
throws Exception
{
return Mode.CR.equals(determineEOL(textFile));
}
/**
* Checks whether the given text file has line endings that conform to the system default mode (e.g. LF on Unix).
*
* @param textFile the file to investigate
* @return
* @throws Exception
*/
public static boolean hasSystemDefaultEOL(File textFile)
throws Exception
{
return SYSTEM_DEFAULT.equals(determineEOL(textFile));
}
/**
* Convert the line endings in the given file to Unix-style (LF).
*
* @param textFile the file to process
* @throws IOException
*/
public static void convertToUnixEOL(File textFile)
throws IOException
{
convertLineEndings(textFile, EOL_UNIX);
}
/**
* Convert the line endings in the given file to Windows-style (CRLF).
*
* @param textFile the file to process
* @throws IOException
*/
public static void convertToWindowsEOL(File textFile)
throws IOException
{
convertLineEndings(textFile, EOL_WINDOWS);
}
/**
* Convert the line endings in the given file to "Old Mac"-style (CR).
*
* @param textFile the file to process
* @throws IOException
*/
public static void convertToOldMacEOL(File textFile)
throws IOException
{
convertLineEndings(textFile, EOL_OLD_MAC);
}
/**
* Convert the line endings in the given file to the system default mode.
*
* @param textFile the file to process
* @throws IOException
*/
public static void convertToSystemEOL(File textFile)
throws IOException
{
convertLineEndings(textFile, EOL_SYSTEM_DEFAULT);
}
/**
* Line endings conversion method.
*
* @param textFile the file to process
* @param eol the end-of-line marker to use (as a {@link String})
* @throws IOException
*/
private static void convertLineEndings(File textFile, String eol)
throws IOException
{
File temp = null;
BufferedReader bufferIn = null;
BufferedWriter bufferOut = null;
try
{
if (textFile.exists())
{
// Create a new temp file to write to
temp = new File(textFile.getAbsolutePath() + ".normalized");
temp.createNewFile();
// Get a stream to read from the file un-normalized file
FileInputStream fileIn = new FileInputStream(textFile);
DataInputStream dataIn = new DataInputStream(fileIn);
bufferIn = new BufferedReader(new InputStreamReader(dataIn));
// Get a stream to write to the normalized file
FileOutputStream fileOut = new FileOutputStream(temp);
DataOutputStream dataOut = new DataOutputStream(fileOut);
bufferOut = new BufferedWriter(new OutputStreamWriter(dataOut));
// For each line in the un-normalized file
String line;
while ((line = bufferIn.readLine()) != null)
{
// Write the original line plus the operating-system dependent newline
bufferOut.write(line);
bufferOut.write(eol); // write EOL marker
}
// Close buffered reader & writer:
bufferIn.close();
bufferOut.close();
// Remove the original file
textFile.delete();
// And rename the original file to the new one
temp.renameTo(textFile);
}
else
{
// If the file doesn't exist...
throw new IOException("Could not find file to open: " + textFile.getAbsolutePath());
}
}
finally
{
// Clean up, temp should never exist
FileUtils.deleteQuietly(temp);
IOUtils.closeQuietly(bufferIn);
IOUtils.closeQuietly(bufferOut);
}
}
}
public static String normalize(String val) {
return val.replace("\r\n", "\n")
.replace("\r", "\n");
}
對於HTML:
public static String normalize(String val) {
return val.replace("\r\n", "<br/>")
.replace("\n", "<br/>")
.replace("\r", "<br/>");
}
的解決方案來改變路徑以遞歸搜索結尾的文件
package handleFileLineEnd;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import sun.awt.image.BytePackedRaster;
public class handleFileEndingMain {
static int carriageReturnTotal;
static int newLineTotal;
public static void main(String[] args) throws IOException
{
processPath("c:/temp/directories");
System.out.println("carriageReturnTotal (files have issue): " + carriageReturnTotal);
System.out.println("newLineTotal: " + newLineTotal);
}
private static void processPath(String path) throws IOException
{
File dir = new File(path);
File[] directoryListing = dir.listFiles();
if (directoryListing != null) {
for (File child : directoryListing) {
if (child.isDirectory())
processPath(child.toString());
else
checkFile(child.toString());
}
}
}
private static void checkFile(String fileName) throws IOException
{
Path path = FileSystems.getDefault().getPath(fileName);
byte[] bytes= Files.readAllBytes(path);
for (int counter=0; counter<bytes.length; counter++)
{
if (bytes[counter] == 13)
{
carriageReturnTotal = carriageReturnTotal + 1;
System.out.println(fileName);
modifyFile(fileName);
break;
}
if (bytes[counter] == 10)
{
newLineTotal = newLineTotal+ 1;
//System.out.println(fileName);
break;
}
}
}
private static void modifyFile(String fileName) throws IOException
{
Path path = Paths.get(fileName);
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll("\r\n", "\n");
content = content.replaceAll("\r", "\n");
Files.write(path, content.getBytes(charset));
}
}
雖然String.replaceAll()是簡單的代碼,這應該執行得更好,因爲它不通過正則表達式基礎結構。
/**
* Accepts a non-null string and returns the string with all end-of-lines
* normalized to a \n. This means \r\n and \r will both be normalized to \n.
* <p>
* Impl Notes: Although regex would have been easier to code, this approach
* will be more efficient since it's purpose built for this use case. Note we only
* construct a new StringBuilder and start appending to it if there are new end-of-lines
* to be normalized found in the string. If there are no end-of-lines to be replaced
* found in the string, this will simply return the input value.
* </p>
*
* @param inputValue !null, input value that may or may not contain new lines
* @return the input value that has new lines normalized
*/
static String normalizeNewLines(String inputValue){
StringBuilder stringBuilder = null;
int index = 0;
int len = inputValue.length();
while (index < len){
char c = inputValue.charAt(index);
if (c == '\r'){
if (stringBuilder == null){
stringBuilder = new StringBuilder();
// build up the string builder so it contains all the prior characters
stringBuilder.append(inputValue.substring(0, index));
}
if ((index + 1 < len) &&
inputValue.charAt(index + 1) == '\n'){
// this means we encountered a \r\n ... move index forward one more character
index++;
}
stringBuilder.append('\n');
}else{
if (stringBuilder != null){
stringBuilder.append(c);
}
}
index++;
}
return stringBuilder == null ? inputValue : stringBuilder.toString();
}
現代Macs(即那些OS X在它們上面)使用LF作爲行終止符。 – JeremyP 2010-09-23 09:45:37