Android-提取特定行的有效方法';s来自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

我有一个包含高程的地形数据,如下所示

每个文件由1440000行组成

.
.
.
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;
}