2010-09-23 98 views
15

我有一個Linux服務器和許多操作系統的客戶端。服務器從客戶端獲取輸入文件。 Linux有行尾char LF,而Mac有行尾char CR,並且 Windows有行尾char CR + LF如何規範Java中的EOL字符?

服務器需要結束行char LF。使用java,我想確保該文件將始終使用linux eol char LF。我怎樣才能實現它?

+1

現代Macs(即那些OS X在它們上面)使用LF作爲行終止符。 – JeremyP 2010-09-23 09:45:37

回答

17

結合兩個答案(由面貌& 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 
+0

不錯,但我不能做任何服務器端。我需要一些東西來做客戶端。像轉換也許.. – bilal 2010-09-23 11:38:54

+0

在客戶端做同樣的事情。看到修改後的答案。你在談論什麼類型的轉換?如果你的意思是編碼,那麼這是一個單獨的問題,與EOL無關。 – lalli 2010-09-23 13:33:07

+3

無論這是否回答OP的問題,爲什麼正則表達式排在第一位?你不是在尋找模式,而是爲了一個固定的字符序列。那麼爲什麼不只是使用'replace()'方法來替換字符? – BalusC 2010-09-23 13:34:47

8

你可以試試嗎?

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

我已經用「\ n」全部換行 – bilal 2010-09-23 11:26:49

2

使用

System.getProperty("line.separator") 

這會給你的(本地)EOL字符(S)。然後,您可以使用incomifile的分析來確定它的「味道」並據此進行轉換。

或者,讓您的客戶標準化!

+0

我將如何使用它?我不需要本地設置,我總是需要linux的設置,我的意思是LF文件結束,即使文件將在窗口生成 – bilal 2010-09-23 10:59:56

+0

通過我想做這個客戶端,而不是服務器端的方式。 – bilal 2010-09-23 11:11:30

6

必須爲最近的項目做到這一點。下面的方法會將給定文件中的行尾標準化爲由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); 
    } 
} 
2

這裏是一個全面的幫助類來處理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); 
     } 
    } 

} 
0
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/>"); 
} 
0

的解決方案來改變路徑以遞歸搜索結尾的文件

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)); 
    } 
} 
0

雖然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(); 
}