如何规范Java中的EOL字符?

我有一个Linux服务器和许多具有许多操作系统的客户端。 服务器从客户端获取输入文件。 Linux具有行尾char LF,而Mac具有行尾char CR,而Windows具有行尾char CR + LF

服务器需要作为行尾char LF。 使用java,我想确保该文件将始终使用linux eol char LF。 我怎样才能实现它?

结合两个答案(Visage&eumiro):

编辑: 阅读评论后。 线。 System.getProperty(“line.separator”)没有用。
在将文件发送到服务器之前,打开它替换所有EOL并回写
确保使用DataStreams这样做,并用二进制文件写

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 

你能试试吗?

 content.replaceAll("\\r\\n?", "\n") 

不得不为最近的项目做这件事。 下面的方法将给定文件中的行结尾规范化为运行JVM的OS指定的行结尾。 因此,如果您在Linux上运行JVM,则会将所有行结尾规范化为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); } } 

使用

 System.getProperty("line.separator") 

这将为您提供(本地)EOL角色。 然后,您可以使用对incomifile的分析来确定它的“味道”并相应地进行转换。

或者,让您的客户标准化!

这是一个全面的帮助类来处理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 (eg 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", "
") .replace("\n", "
") .replace("\r", "
"); }

解决方案来更改以路径中的递归搜索结尾的文件

 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 

尽管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. * 

* 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. *

* * @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(); }