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