Android-提取特定行的有效方法';s来自1440000行文本文件的数据
我有一个包含高程的地形数据,如下所示 每个文件由1440000行组成Android-提取特定行的有效方法';s来自1440000行文本文件的数据,android,file,random-access,Android,File,Random Access,我有一个包含高程的地形数据,如下所示 每个文件由1440000行组成 . . . 183 192 127 . . . 如何直接从文件中访问特定行,而不浪费完整的数据内存负载? (在Android中)您可能希望使用BufferedInputStream: 您可能希望使用BufferedInputStream: 我认为,您可以使用java.nio.FileChannel.read(缓冲区、开始、编号) start表示开始偏移量,number表示要读取的字节数。我认为,您可以使用java.nio.F
.
.
.
183
192
127
.
.
.
如何直接从文件中访问特定行,而不浪费完整的数据内存负载?
(在Android中)您可能希望使用BufferedInputStream:
您可能希望使用BufferedInputStream:
我认为,您可以使用java.nio.FileChannel.read(缓冲区、开始、编号)
start表示开始偏移量,number表示要读取的字节数。我认为,您可以使用java.nio.FileChannel.read(缓冲区,start,number)
开始表示开始偏移量,数字表示要读取的字节数。如果可以将文件更改为二进制格式,则可以直接查找到所需的位置,然后读取所需的值。如果没有,您可能需要逐行读取并返回所需的行(假设无法计算字节位置,因为行的长度可能不同) 在玩了太久之后,我得到了这个(虽然它没有经过测试):
File f=新文件(“yourfile.txt”);
HashMap结果=读取行(f,1,5,255);
字符串line5=结果。获取(5);//如果文件没有第5行,则为null
私有静态HashMap读取行(文件f,int…行){
HashMap结果=新建HashMap();
HashSet linesSet=新HashSet();
for(int行:行){
linesSet.add(整型.valueOf(line));
}
BufferedReader br=null;
试一试{
br=新的BufferedReader(新的InputStreamReader(新文件InputStream(f),“UTF-8”);
int line=1;//从第1行开始
字符串currentLine=null;
而((currentLine=br.readLine())!=null){
整数i=整数。值(行);
如果(线路集包含(i))
结果。输入(i,电流线);
line++;
}
}catch(filenotfounde异常){
//找不到文件
}捕获(不支持的编码异常e){
//指定了错误的编码
}捕获(IOE异常){
//看不懂
}最后{
如果(br!=null){
试一试{
br.close();
}捕获(IOE异常){
//忽略。
}
}
}
返回结果;
}
如果您可以将文件更改为二进制格式,则可以直接查找到所需的位置,然后读取所需的值。如果没有,您可能需要逐行读取并返回所需的行(假设无法计算字节位置,因为行的长度可能不同)
在玩了太久之后,我得到了这个(虽然它没有经过测试):
File f=新文件(“yourfile.txt”);
HashMap结果=读取行(f,1,5,255);
字符串line5=结果。获取(5);//如果文件没有第5行,则为null
私有静态HashMap读取行(文件f,int…行){
HashMap结果=新建HashMap();
HashSet linesSet=新HashSet();
for(int行:行){
linesSet.add(整型.valueOf(line));
}
BufferedReader br=null;
试一试{
br=新的BufferedReader(新的InputStreamReader(新文件InputStream(f),“UTF-8”);
int line=1;//从第1行开始
字符串currentLine=null;
而((currentLine=br.readLine())!=null){
整数i=整数。值(行);
如果(线路集包含(i))
结果。输入(i,电流线);
line++;
}
}catch(filenotfounde异常){
//找不到文件
}捕获(不支持的编码异常e){
//指定了错误的编码
}捕获(IOE异常){
//看不懂
}最后{
如果(br!=null){
试一试{
br.close();
}捕获(IOE异常){
//忽略。
}
}
}
返回结果;
}
如果记录是固定长度的,您可以计算并直接转到所需记录的字节位置
如果记录长度可变,但包含非常大文件的顺序标识信息(如记录编号),则可能值得根据平均记录长度猜测起始位置,在该位置之前搜索一位,然后向前读取以找到所需的行(如果您已经过了该行,请备份一位)
如果除了从头开始计数之外,没有其他方法来识别记录,那么您必须这样做。理想情况下,这样做的方式不会在扫描过程中反复创建对象,然后让垃圾收集器清理它们……如果记录长度固定,则可以计算并直接转到所需记录的字节位置 如果记录长度可变,但包含非常大文件的顺序标识信息(如记录编号),则可能值得根据平均记录长度猜测起始位置,在该位置之前搜索一位,然后向前读取以找到所需的行(如果您已经过了该行,请备份一位)
如果除了从头开始计数之外,没有其他方法来识别记录,那么您必须这样做。理想情况下,您这样做的方式不会在扫描过程中反复创建对象,然后让垃圾收集器清理它们…我认为您最好的选择是将文本文件转换为SQLite数据库。我认为您最好的选择是将文本文件转换为SQLite数据库。问题不在于它是否是一个数据库二进制格式,但如果它是固定长度的记录格式。@ChrisStratton您是对的,二进制并不意味着固定长度的记录。我实际上的意思是:一个简单的流,例如
int
保证是固定长度的,非常容易读/写(-endianess),可能更小(“123\n”已经是4个字节了)&计算所需位置比文本表示法更容易,在文本表示法中可以有\r\n
,BOM头
File f = new File ("yourfile.txt");
HashMap <Integer, String> result = readLines(f, 1, 5, 255);
String line5 = result.get(5); // or null if the file had no line 5
private static HashMap <Integer, String> readLines(File f, int... lines) {
HashMap<Integer, String> result = new HashMap<Integer, String>();
HashSet<Integer> linesSet = new HashSet<Integer>();
for (int line : lines) {
linesSet.add(Integer.valueOf(line));
}
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
int line = 1; // starting at line 1
String currentLine = null;
while ((currentLine = br.readLine()) != null) {
Integer i = Integer.valueOf(line);
if (linesSet.contains(i))
result.put(i, currentLine);
line++;
}
} catch (FileNotFoundException e) {
// file not found
} catch (UnsupportedEncodingException e) {
// bad encoding specified
} catch (IOException e) {
// could not read
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
// ignore.
}
}
}
return result;
}