1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 16 package org.tensorflow.lite.support.common; 17 18 import android.content.Context; 19 import android.content.res.AssetFileDescriptor; 20 import java.io.BufferedReader; 21 import java.io.FileInputStream; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.InputStreamReader; 25 import java.nio.ByteBuffer; 26 import java.nio.MappedByteBuffer; 27 import java.nio.channels.FileChannel; 28 import java.nio.charset.Charset; 29 import java.util.ArrayList; 30 import java.util.List; 31 import org.checkerframework.checker.nullness.qual.NonNull; 32 33 /** File I/O utilities. */ 34 public class FileUtil { FileUtil()35 private FileUtil() {} 36 37 /** 38 * Loads labels from the label file into a list of strings. 39 * 40 * <p>A legal label file is the plain text file whose contents are split into lines, and each line 41 * is an individual value. The file should be in assets of the context. 42 * 43 * @param context The context holds assets. 44 * @param filePath The path of the label file, relative with assets directory. 45 * @return a list of labels. 46 * @throws IOException if error occurs to open or read the file. 47 */ 48 @NonNull loadLabels(@onNull Context context, @NonNull String filePath)49 public static List<String> loadLabels(@NonNull Context context, @NonNull String filePath) 50 throws IOException { 51 return loadLabels(context, filePath, Charset.defaultCharset()); 52 } 53 54 /** 55 * Loads labels from the label file into a list of strings. 56 * 57 * <p>A legal label file is the plain text file whose contents are split into lines, and each line 58 * is an individual value. The empty lines will be ignored. The file should be in assets of the 59 * context. 60 * 61 * @param context The context holds assets. 62 * @param filePath The path of the label file, relative with assets directory. 63 * @param cs {@code Charset} to use when decoding content of label file. 64 * @return a list of labels. 65 * @throws IOException if error occurs to open or read the file. 66 */ 67 @NonNull loadLabels( @onNull Context context, @NonNull String filePath, Charset cs)68 public static List<String> loadLabels( 69 @NonNull Context context, @NonNull String filePath, Charset cs) throws IOException { 70 SupportPreconditions.checkNotNull(context, "Context cannot be null."); 71 SupportPreconditions.checkNotNull(filePath, "File path cannot be null."); 72 try (InputStream inputStream = context.getAssets().open(filePath)) { 73 return loadLabels(inputStream, cs); 74 } 75 } 76 77 /** 78 * Loads labels from an input stream of an opened label file. See details for label files in 79 * {@link FileUtil#loadLabels(Context, String)}. 80 * 81 * @param inputStream the input stream of an opened label file. 82 * @return a list of labels. 83 * @throws IOException if error occurs to open or read the file. 84 */ 85 @NonNull loadLabels(@onNull InputStream inputStream)86 public static List<String> loadLabels(@NonNull InputStream inputStream) throws IOException { 87 return loadLabels(inputStream, Charset.defaultCharset()); 88 } 89 90 /** 91 * Loads labels from an input stream of an opened label file. See details for label files in 92 * {@link FileUtil#loadLabels(Context, String)}. 93 * 94 * @param inputStream the input stream of an opened label file. 95 * @param cs {@code Charset} to use when decoding content of label file. 96 * @return a list of labels. 97 * @throws IOException if error occurs to open or read the file. 98 */ 99 @NonNull loadLabels(@onNull InputStream inputStream, Charset cs)100 public static List<String> loadLabels(@NonNull InputStream inputStream, Charset cs) 101 throws IOException { 102 List<String> labels = new ArrayList<>(); 103 try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, cs))) { 104 String line; 105 while ((line = reader.readLine()) != null) { 106 if (line.trim().length() > 0) { 107 labels.add(line); 108 } 109 } 110 return labels; 111 } 112 } 113 114 /** 115 * Loads a vocabulary file (a single-column text file) into a list of strings. 116 * 117 * <p>A vocabulary file is a single-column plain text file whose contents are split into lines, 118 * and each line is an individual value. The file should be in assets of the context. 119 * 120 * @param context The context holds assets. 121 * @param filePath The path of the vocabulary file, relative with assets directory. 122 * @return a list of vocabulary words. 123 * @throws IOException if error occurs to open or read the file. 124 */ 125 @NonNull loadSingleColumnTextFile( @onNull Context context, @NonNull String filePath, Charset cs)126 public static List<String> loadSingleColumnTextFile( 127 @NonNull Context context, @NonNull String filePath, Charset cs) throws IOException { 128 return loadLabels(context, filePath, cs); 129 } 130 131 /** 132 * Loads vocabulary from an input stream of an opened vocabulary file (which is a single-column 133 * text file). See details for vocabulary files in {@link FileUtil#loadVocabularyFile(Context, 134 * String)}. 135 * 136 * @param inputStream the input stream of an opened vocabulary file. 137 * @return a list of vocabulary words. 138 * @throws IOException if error occurs to open or read the file. 139 */ 140 @NonNull loadSingleColumnTextFile(@onNull InputStream inputStream, Charset cs)141 public static List<String> loadSingleColumnTextFile(@NonNull InputStream inputStream, Charset cs) 142 throws IOException { 143 return loadLabels(inputStream, cs); 144 } 145 146 /** 147 * Loads a file from the asset folder through memory mapping. 148 * 149 * @param context Application context to access assets. 150 * @param filePath Asset path of the file. 151 * @return the loaded memory mapped file. 152 * @throws IOException if an I/O error occurs when loading the tflite model. 153 */ 154 @NonNull loadMappedFile(@onNull Context context, @NonNull String filePath)155 public static MappedByteBuffer loadMappedFile(@NonNull Context context, @NonNull String filePath) 156 throws IOException { 157 SupportPreconditions.checkNotNull(context, "Context should not be null."); 158 SupportPreconditions.checkNotNull(filePath, "File path cannot be null."); 159 try (AssetFileDescriptor fileDescriptor = context.getAssets().openFd(filePath); 160 FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor())) { 161 FileChannel fileChannel = inputStream.getChannel(); 162 long startOffset = fileDescriptor.getStartOffset(); 163 long declaredLength = fileDescriptor.getDeclaredLength(); 164 return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength); 165 } 166 } 167 168 /** 169 * Loads a binary file from the asset folder. 170 * 171 * @param context Application context to access assets. 172 * @param filePath Asset path of the file. 173 * @return the byte array for the binary file. 174 * @throws IOException if an I/O error occurs when loading file. 175 */ 176 @NonNull loadByteFromFile(@onNull Context context, @NonNull String filePath)177 public static byte[] loadByteFromFile(@NonNull Context context, @NonNull String filePath) 178 throws IOException { 179 ByteBuffer buffer = loadMappedFile(context, filePath); 180 byte[] byteArray = new byte[buffer.remaining()]; 181 buffer.get(byteArray); 182 return byteArray; 183 } 184 } 185