2010-06-18 7 views
0

J'ai écrit la méthode suivante pour déterminer si le fichier en question est formaté avec des fins de ligne DOS/MAC ou UNIX.Comment déterminer le format de fichier? DOS/Unix/MAC

Je vois au moins 1 problème évident: 1. j'espère que j'obtiendrai l'EOL sur la première exécution, disons dans les 1000 premiers octets. Cela peut ou peut ne pas arriver.

Je vous demande de revoir ceci et de suggérer des améliorations qui vont conduire à durcir le code et à le rendre plus générique.

MERCI.

new FileFormat().discover(fileName, 0, 1000); 

puis

public void discover(String fileName, int offset, int depth) throws IOException { 

    BufferedInputStream in = new BufferedInputStream(new FileInputStream(fileName)); 
    FileReader a = new FileReader(new File(fileName)); 

    byte[] bytes = new byte[(int) depth]; 
    in.read(bytes, offset, depth); 

    a.close(); 
    in.close(); 
    int thisByte; 
    int nextByte; 

    boolean isDos = false; 
    boolean isUnix = false; 
    boolean isMac = false; 

    for (int i = 0; i < (bytes.length - 1); i++) { 
     thisByte = bytes[i]; 
     nextByte = bytes[i + 1]; 
    if (thisByte == 10 && nextByte != 13) { 
      isDos = true; 
      break; 
     } else if (thisByte == 13) { 
      isUnix = true; 
      break; 
     } else if (thisByte == 10) { 
      isMac = true; 
      break; 
     } 
    } 
    if (!(isDos || isMac || isUnix)) { 
      discover(fileName, offset + depth, depth + 1000); 
    } else { 
     // do something clever 
    } 
} 
+1

Que diable faites-vous avec le FileReader a? Et quoi de neuf avec le décalage? –

+0

rien. oublié de l'enlever. – JAM

Répondre

3

Votre méthode semble inutilement compliquée. Pourquoi ne pas:

public class FileFormat { 
    public enum FileType { WINDOWS, UNIX, MAC, UNKNOWN } 

    private static final char CR = '\r'; 
    private static final char LF = '\n'; 

    public static FileType discover(String fileName) throws IOException {  

     Reader reader = new BufferedReader(new FileReader(fileName)); 
     FileType result = discover(reader); 
     reader.close(); 
     return result; 
    } 

    private static FileType discover(Reader reader) throws IOException { 
     int c; 
     while ((c = reader.read()) != -1) { 
      switch(c) {   
      case LF: return FileType.UNIX; 
      case CR: { 
       if (reader.read() == LF) return FileType.WINDOWS; 
       return FileType.MAC; 
      } 
      default: continue; 
      } 
     } 
     return FileType.UNKNOWN; 
    } 
} 

qui met cela dans une méthode statique que vous pouvez appeler et utiliser comme:

switch(FileFormat.discover(fileName) { 
case WINDOWS: ... 
case MAC: ... 
case UNKNOWN: ... 
} 
+0

Merci Dean! – JAM

+0

Excellent, exactement ce dont j'avais besoin, merci beaucoup! – dimo414

+0

@DeanPovey J'essaie d'utiliser ce qui précède pour déterminer le séparateur de ligne imprimé dans un autre fichier. Cependant cela ne fonctionne pas. –

0

Il y a beaucoup de mal à cela. Vous devez mieux comprendre la classe FileInputStream. Notez que read n'est pas garanti pour lire tous les octets que vous avez demandés. offset est le décalage dans le tableau, pas le fichier. Etc.

1

Voici une mise en œuvre difficile qui devine le type de fin de ligne à la majorité simple et chutes retour sur inconnu dans le pire des cas:

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileReader; 
import java.util.EnumMap; 
import java.util.Map; 
import java.util.Scanner; 

class LineEndings 
{ 
    private enum ExitState 
    { 
     SUCCESS, FAILURE; 
    } 

    public enum LineEndingType 
    { 
     DOS("Windows"), MAC("Mac OS Classic"), UNIX("Unix/Linux/Mac OS X"), UNKNOWN("Unknown"); 

     private final String name; 
     private LineEndingType(String name) 
     { 
      this.name = name; 
     } 

     public String toString() 
     { 
      if (null == this.name) { 
       return super.toString(); 
      } 
      else { 
       return this.name; 
      } 
     } 
    } 

    public static void main(String[] arguments) 
    { 
     ExitState exitState = ExitState.SUCCESS; 

     File inputFile = getInputFile(); 

     if (null == inputFile) { 
      exitState = ExitState.FAILURE; 

      System.out.println("Error: No input file specified."); 
     } 
     else { 
      System.out.println("Determining line endings for: " + inputFile.getName()); 

      try { 
       LineEndingType lineEndingType = getLineEndingType(inputFile); 

       System.out.println("Determined line endings: " + lineEndingType); 
      } 
      catch (java.io.IOException exception) { 
       exitState = ExitState.FAILURE; 

       System.out.println("Error: " + exception.getMessage()); 
      } 
     } 

     switch (exitState) { 
     case SUCCESS: 
      System.exit(0); 
      break; 
     case FAILURE: 
      System.exit(1); 
      break; 
     } 
    } 

    private static File getInputFile() 
    { 
     File inputFile = null; 
     Scanner stdinScanner = new Scanner(System.in); 

     while (true) { 
      System.out.println("Enter the input file name:"); 
      System.out.print(">> "); 

      if (stdinScanner.hasNext()) { 
       String inputFileName = stdinScanner.next(); 

       inputFile = new File(inputFileName); 

       if (!inputFile.exists()) { 
        System.out.println("File not found.\n"); 
       } 
       else if (!inputFile.canRead()) { 
        System.out.println("Could not read file.\n"); 
       } 
       else { 
        break; 
       } 
      } 
      else { 
       inputFile = null; 
       break; 
      } 
     } 

     System.out.println(); 

     return inputFile; 
    } 

    private static LineEndingType getLineEndingType(File inputFile) 
     throws java.io.IOException, java.io.FileNotFoundException 
    { 
     EnumMap<LineEndingType, Integer> lineEndingTypeCount = 
      new EnumMap<LineEndingType, Integer>(LineEndingType.class); 

     BufferedReader inputReader = new BufferedReader(new FileReader(inputFile)); 

     LineEndingType currentLineEndingType = null; 

     while (inputReader.ready()) { 
      int token = inputReader.read(); 

      if ('\n' == token) { 
       currentLineEndingType = LineEndingType.UNIX; 
      } 
      else if ('\r' == token) { 
       if (inputReader.ready()) { 
        int nextToken = inputReader.read(); 

        if ('\n' == nextToken) { 
         currentLineEndingType = LineEndingType.DOS; 
        } 
        else { 
         currentLineEndingType = LineEndingType.MAC; 
        } 
       } 
      } 

      if (null != currentLineEndingType) { 
       incrementLineEndingType(lineEndingTypeCount, currentLineEndingType); 

       currentLineEndingType = null; 
      } 
     } 

     return getMostFrequentLineEndingType(lineEndingTypeCount); 
    } 

    private static void incrementLineEndingType(Map<LineEndingType, Integer> lineEndingTypeCount, LineEndingType targetLineEndingType) 
    { 
     Integer targetLineEndingCount = lineEndingTypeCount.get(targetLineEndingType); 

     if (null == targetLineEndingCount) { 
      targetLineEndingCount = 0; 
     } 
     else { 
      targetLineEndingCount++; 
     } 

     lineEndingTypeCount.put(targetLineEndingType, targetLineEndingCount); 
    } 

    private static LineEndingType getMostFrequentLineEndingType(Map<LineEndingType, Integer> lineEndingTypeCount) 
    { 
     Integer maximumEntryCount = Integer.MIN_VALUE; 

     Map.Entry<LineEndingType, Integer> mostFrequentEntry = null; 

     for (Map.Entry<LineEndingType, Integer> entry : lineEndingTypeCount.entrySet()) { 
      int entryCount = entry.getValue(); 

      if (entryCount > maximumEntryCount) { 
       mostFrequentEntry = entry; 
       maximumEntryCount = entryCount; 
      } 
     } 

     if (null != mostFrequentEntry) { 
      return mostFrequentEntry.getKey(); 
     } 
     else { 
      return LineEndingType.UNKNOWN; 
     } 
    } 
} 
Questions connexes