001package org.unix4j.io; 002 003import java.io.File; 004import java.io.FileDescriptor; 005import java.io.FileInputStream; 006import java.io.FileNotFoundException; 007import java.io.FileReader; 008import java.io.InputStreamReader; 009import java.util.ArrayList; 010import java.util.List; 011 012import org.unix4j.util.FileUtil; 013 014/** 015 * Input device reading from a {@link File}. 016 */ 017public class FileInput extends ReaderInput { 018 019 private final String fileInfo; 020 021 public FileInput(FileReader fileReader) { 022 super(fileReader); 023 this.fileInfo = fileReader.toString(); 024 } 025 026 public FileInput(File currentDirectory, File file) { 027 super(createFileReader(currentDirectory, file)); 028 this.fileInfo = file.toString(); 029 } 030 031 public FileInput(File file) { 032 super(createFileReader(file)); 033 this.fileInfo = file.toString(); 034 } 035 036 public FileInput(FileInputStream fileStream) { 037 super(new InputStreamReader(fileStream)); 038 this.fileInfo = fileStream.toString(); 039 } 040 041 public FileInput(FileDescriptor fileDesc) { 042 super(new FileReader(fileDesc)); 043 this.fileInfo = fileDesc.toString(); 044 } 045 046 public FileInput(String file) { 047 this(new File(file)); 048 } 049 public FileInput(File currentDirectory, String file) { 050 this(currentDirectory, new File(file)); 051 } 052 053 /** 054 * Creates a new {@link FileInput} object for each of the specified files 055 * and resturns a list with all input objects. 056 * 057 * @param files 058 * the files for whose to create a {@code FileInput} object 059 */ 060 public static List<FileInput> multiple(File... files) { 061 final List<FileInput> inputs = new ArrayList<FileInput>(files.length); 062 for (int i = 0; i < files.length; i++) { 063 inputs.add(new FileInput(files[i])); 064 } 065 return inputs; 066 } 067 068 /** 069 * Creates a new {@link FileInput} object for each of the specified files 070 * and resturns a list with all input objects. 071 * 072 * @param files 073 * the files for whose to create a {@code FileInput} object 074 */ 075 public static List<FileInput> multiple(List<File> files) { 076 final List<FileInput> inputs = new ArrayList<FileInput>(files.size()); 077 for (int i = 0; i < files.size(); i++) { 078 inputs.add(new FileInput(files.get(i))); 079 } 080 return inputs; 081 } 082 083 /** 084 * Creates and returns an input composed from the specified files 085 * altogether. The resulting input object returns the lines lines of the 086 * first file first, then the lines of the second file etc. 087 * 088 * @param files 089 * the files to combine into a single input object 090 */ 091 public static Input composite(File... files) { 092 if (files.length == 0) 093 return NullInput.INSTANCE; 094 if (files.length == 1) 095 return new FileInput(files[0]); 096 return new CompositeInput(multiple(files)); 097 } 098 099 /** 100 * Creates and returns an input composed from the specified files 101 * altogether. The resulting input object returns the lines lines of the 102 * first file first, then the lines of the second file etc. 103 * 104 * @param files 105 * the files to combine into a single input object 106 */ 107 public static Input composite(List<File> files) { 108 if (files.size() == 0) 109 return NullInput.INSTANCE; 110 if (files.size() == 1) 111 return new FileInput(files.get(0)); 112 return new CompositeInput(multiple(files)); 113 } 114 115 private static FileReader createFileReader(File file) { 116 try { 117 return new FileReader(file); 118 } catch (FileNotFoundException e) { 119 throw new RuntimeException(e); 120 } 121 } 122 123 private static FileReader createFileReader(File currentDirectory, File path) { 124 try { 125 final File file = FileUtil.toAbsoluteFile(currentDirectory, path); 126 return new FileReader(file); 127 } catch (FileNotFoundException e) { 128 throw new RuntimeException(e); 129 } 130 } 131 132 /** 133 * Returns the file info string, for instance a file path or file name. 134 * 135 * @return the file info string, usually the file name or path. 136 */ 137 public String getFileInfo() { 138 return fileInfo; 139 } 140 141 /** 142 * Returns the file info string relative to the given root directory. If a 143 * relative path cannot be evaluated, the method defaults to 144 * {@link #getFileInfo()}. 145 * 146 * @param relativeRoot 147 * the relative root for the returned path, may be ignored if a 148 * relative path cannot be evaluated for the underlying source 149 * object 150 * @return the file info string, usually the file name or path relative to 151 * the given root directory 152 */ 153 public String getFileInfo(File relativeRoot) { 154 try { 155 return FileUtil.getRelativePath(relativeRoot, new File(fileInfo)); 156 } catch (Exception e) { 157 return getFileInfo(); 158 } 159 } 160 161 @Override 162 public String toString() { 163 return getClass().getSimpleName() + "(fileInfo=" + getFileInfo() + ")"; 164 } 165}