如何用SQLite脚本逐行读取.txt文件?

hjqgdpho  于 2023-02-09  发布在  SQLite
关注(0)|答案(6)|浏览(336)

我正在做一个有数据库的项目。这个数据库非常简单。只有一个表,有2列:id(int)和text(string)。为了填充这个基础,我想创建一个. sql脚本文件。(这个数据库不是在android项目中创建的,因为我想在我的android项目中插入一个已经填充的数据库)
我希望我的脚本创建表,然后读取一个. txt文件,每行都有一个字符串值(文本列)。对于每一行,它都应该将字符串值插入到表中。
我对SQLite和SQL不是很熟悉,我已经找到了一种使用迭代器自动递增id的方法(但我还没有测试它),但我找不到如何逐行读取. txt文件。

  • 所以我的问题是:是否可以在SQLite脚本中逐行读取. txt文件?
  • 如果是的话,你能告诉我怎么做吗?
b5buobof

b5buobof1#

这里有一个纯sqlite的解决方案

CREATE TEMP TABLE input (value STRING);
INSERT INTO input VALUES (TRIM(readfile('input.txt'), char(10)));

CREATE TABLE lines (s STRING);
WITH RECURSIVE
    nn (s, rest)
AS (
    SELECT
        (SELECT SUBSTR(input.value, 0, INSTR(input.value, char(10))) FROM input),
        (SELECT SUBSTR(input.value, INSTR(input.value, char(10)) + 1) FROM input)
    UNION ALL
    SELECT
        CASE INSTR(nn.rest, char(10))
            WHEN 0 THEN nn.rest
            ELSE SUBSTR(nn.rest, 0, INSTR(nn.rest, char(10)))
        END,
        CASE INSTR(nn.rest, char(10))
            WHEN 0 THEN ''
            ELSE SUBSTR(nn.rest, INSTR(nn.rest, char(10)) + 1)
        END
    FROM nn
    WHERE LENGTH(nn.rest) > 0
)
INSERT INTO lines (s)
SELECT nn.s FROM nn;

DROP TABLE input;

这里有一些微妙之处:

  • sqlite没有\n转义,因此必须使用char(10)
  • 这对于混合换行符或\r\n换行符效果不佳(尽管您可以将一些+ 1调整为+ 2,将char(10)调整为char(13) || char(10)
  • 最神奇的地方在于中间的递归联合,它一次只吃一行

注意,我使用这种方法来解决代码出现的问题--https://github.com/anthonywritescode/aoc2020

e5nszbig

e5nszbig2#

SQLite是一个嵌入式数据库;它被设计为与一些“真实的的”编程语言一起使用。没有访问和解析文本文件的函数。
您必须用任何您喜欢的语言编写自己的脚本,或者使用一些现有的工具。
如果文本文件中有保证不会出现的字符,则可以使用sqlite3命令行shell和一个临时的单列表进行导入:

CREATE TEMP TABLE i(txt);
.separator ~
.import MyFile.txt i
INSERT INTO TheRealTable(text) SELECT txt FROM i;  -- assumes id is autoincrementing
DROP TABLE i;
kxxlusnw

kxxlusnw3#

我认为最简单的方法是将txt文件转换为csv文件,然后可以直接导入Sqlite3或通过编程语言导入。
sqlite〉.mode csv表格名称
sqlite〉.import文件名.csv表格名

jtoj6r0c

jtoj6r0c4#

您可以使用BufferedReader来完成此操作。代码可能如下所示:

InputStream in = context.getResources().openRawResource( R.raw.your_txt_file );
BufferedReader reader = new BufferedReader( new InputStreamReader( in ) );

String line = null;
while( null != ( line = reader.readLine() ) ){
  doStuffWithLine( line );
}

reader.close();
4sup72z8

4sup72z85#

是的,在SQLite脚本中逐行读取一个. txt文件是可能的。但是你需要使用一个扩展名。具体来说,sqlean-fileio可以完成这项工作。
它的fileio_scan(path)函数逐行读取path指定的文件,而不是将整个文件加载到内存中。
例如:

$ echo 'one' > data.txt
$ echo 'two' >> data.txt
$ echo 'three' >> data.txt
create table data(id integer primary key, txt text);

insert into data(txt)
select value from fileio_scan('data.txt');

select * from data;
┌────┬───────┐
│ id │  txt  │
├────┼───────┤
│ 1  │ one   │
│ 2  │ two   │
│ 3  │ three │
└────┴───────┘

就是这样!

vbkedwbf

vbkedwbf6#

所以我的问题是:是否可以在SQLite脚本中逐行读取. txt文件?
"是的"
如果是的话,你能告诉我怎么做吗?

    • 我们开始**

伪码算法:
1.打开文件。
1.逐行读取并在数据库中插入新行。
1.关闭资源并提交事务。

    • 1)打开文件**
InputStream instream = new FileInputStream("myfilename.txt");
InputStreamReader inputreader = new InputStreamReader(instream);
BufferedReader buffreader = new BufferedReader(inputreader);
    • 2)逐行读取并在数据库中插入新行**
List<String> nameList = new ArrayList<>();
String line;
do {
    line = buffreader.readLine();
    if (line != null){
        nameList.add(line);
    }
} while (line != null);

现在您应该插入数据库中的所有名称:

storeNamesInDB(nameList);

地点

private void storeNamesInDB(nameList){
    String sql = "INSERT INTO table (col1) VALUES (?)";
    db.beginTransaction();

    SQLiteStatement stmt = db.compileStatement(sql);
    for (int i = 0; i < nameList.size(); i++) {
        stmt.bindString(1, values.get(i));
        stmt.execute();
        stmt.clearBindings();
    }

    db.setTransactionSuccessful();
    db.endTransaction();
}
    • 3)关闭资源**

不要忘记关闭资源:

instream.close();
inputreader.close();
    • 免责声明!你不应该复制粘贴**这段代码。用对你的项目有意义的名字替换每个变量名和一些指令。这只是一个想法。

相关问题