文件读写--格式转化

#include <fstream>
#include <iostream>

using namespace std;

string txtToSql(string infile, string outfile) {
    cout << infile;
    ifstream in(infile);
    ofstream out(outfile);
    string lineIn, lineOut, sqlresult;
//0:数字 1:字符串
    if (in) // 有该文件
    {
        int flag = 0, FL[100], length = 0;
        while (getline(in, lineIn)) // line中不包括每行的换行符
        {
            cout << "line read" << endl;
            if (flag == 0) {
                for (int j = 0; j < lineIn.length(); j++) {
                    FL[j] = lineIn[j] - '0';
                    length++;
                }
                lineOut = "";
                flag++;
                continue;
            }
            flag++;
            lineOut = swtichToSql(lineIn, FL, length);
            if (flag > 2) { lineOut = "," + lineOut; }
            sqlresult = sqlresult + lineOut;
            cout << lineIn << endl;
            cout << lineOut << endl;
            out << lineOut << endl; // 输入到2.txt中
        }
    } else // 没有该文件
    {
        cout << "no such file" << endl;
    }
    cout << sqlresult << endl;
    return sqlresult;
}
//对每一行的文本进行处理:字符串加引号,各单元之间加逗号,整行用括号包起来
string swtichToSql(string str, int a[], int len) {
    string res = "(";
    const char *p = str.c_str();
    for (int i = 0; i < len; i++) {
        char achar[100] = {'\0'};
        char *q = achar;
        if (a[i] == 1) {
            *q = '"';
            q++;
        }
        while (*p != '\0' && *p != '\t') {
            *q = *p;
            q++;
            p++;
        }
        if (a[i] == 1) {
            *q++ = '"';
        }
        if (i < len - 1) {
            *q = ',';
            q++;
        }
        *q = '\0';
        string temp = achar;
        res = res.append(temp);
        while (*p == '\t') {
            p++;
        }

    }
    res = res.append(")");
    return res;
}



int main() {
    string infile = "/Users/fangwendong/work/test.txt", outfile = "/Users/fangwendong/work/result.sql", sqlresult = "";
    //txt ===> sql
    sqlresult = txtToSql(infile, outfile);
    return 0;

}

测试文本test.txt

0010011
109    2704608    4bf12945    83    83        FAILED    2017-08-08
109    2718426    5e9598ee    83    83        FAILED    2017-08-08
109    2726917    8a8ab27f    83    83        FAILED    2017-08-08
109    2040471    47a332c7    83    83            FAILED    2017-08-15
109    2263489    a36309f5    83    83        FAILED    2017-08-15
109    2409650    e210bff6    83    83        FAILED    2017-08-11
109    2409711    34cbff54    83    83        FAILED    2017-08-11
109    2636838    f57a56e6    83    83        FAILED    2017-08-11
109    2725817    aff10c26    83    83        FAILED    2017-08-15
109    2729543    dc4bece7    83       83        FAILED    2017-08-15
109    2753012    fb1f0ef0    83    83        FAILED    2017-08-15
109    2353175    e161bf8e    83    83        FAILED    2017-08-20
109    2363029    4d41ebc8    83    83        FAILED    2017-08-20
109    2363047    82712ba3    83    83        FAILED    2017-08-20
109    2386423    09ef5056    83    83        FAILED    2017-08-20
109    2388536    c2238139    83    83        FAILED    2017-08-20
109    2405661    1d01dcb2    83    83        FAILED    2017-08-20
109    2406788    6dc6838d    83    83        FAILED    2017-08-20
109    2409285    05c1c6b1    83    83        FAILED    2017-08-20
109    2409356    9800a7df    83    83        FAILED    2017-08-20
109    2412893    16c7b6b7    83    83        FAILED    2017-08-20
109    2412970    05bf815e    83    83        FAILED    2017-08-20
109    2421705    66150707    83    83        FAILED    2017-08-20
109    2457426    1fe8b55e    83    83        FAILED    2017-08-20
109    2482453    0f19b58d    83    83        FAILED    2017-08-20

实验结果result.sql

(109,2704608,"4bf12945",83,83,"FAILED","2017-08-08")
,(109,2718426,"5e9598ee",83,83,"FAILED","2017-08-08")
,(109,2726917,"8a8ab27f",83,83,"FAILED","2017-08-08")
,(109,2040471,"47a332c7",83,83,"FAILED","2017-08-15")
,(109,2263489,"a36309f5",83,83,"FAILED","2017-08-15")
,(109,2409650,"e210bff6",83,83,"FAILED","2017-08-11")
,(109,2409711,"34cbff54",83,83,"FAILED","2017-08-11")
,(109,2636838,"f57a56e6",83,83,"FAILED","2017-08-11")
,(109,2725817,"aff10c26",83,83,"FAILED","2017-08-15")
,(109,2729543,"dc4bece7",83,83,"FAILED","2017-08-15")
,(109,2753012,"fb1f0ef0",83,83,"FAILED","2017-08-15")
,(109,2353175,"e161bf8e",83,83,"FAILED","2017-08-20")
,(109,2363029,"4d41ebc8",83,83,"FAILED","2017-08-20")
,(109,2363047,"82712ba3",83,83,"FAILED","2017-08-20")
,(109,2386423,"09ef5056",83,83,"FAILED","2017-08-20")
,(109,2388536,"c2238139",83,83,"FAILED","2017-08-20")
,(109,2405661,"1d01dcb2",83,83,"FAILED","2017-08-20")
,(109,2406788,"6dc6838d",83,83,"FAILED","2017-08-20")
,(109,2409285,"05c1c6b1",83,83,"FAILED","2017-08-20")
,(109,2409356,"9800a7df",83,83,"FAILED","2017-08-20")
,(109,2412893,"16c7b6b7",83,83,"FAILED","2017-08-20")
,(109,2412970,"05bf815e",83,83,"FAILED","2017-08-20")
,(109,2421705,"66150707",83,83,"FAILED","2017-08-20")
,(109,2457426,"1fe8b55e",83,83,"FAILED","2017-08-20")
,(109,2482453,"0f19b58d",83,83,"FAILED","2017-08-20")

 

转载于:https://www.cnblogs.com/fwdqxl/p/7441027.html

<think>嗯,用户想要用C语言实现两个线程进行文件读写的示例。首先,我需要回忆一下C语言中多线程编程的基本方法。记得C标准库本身没有多线程支持,得用POSIX线程库,也就是pthread。所以代码里应该包含pthread.h头文件,并且在编译的时候加上-lpthread选项。 接下来,用户提到两个线程,一个读一个写。这时候需要考虑线程之间的同步问题,否则可能会出现竞态条件。比如,写线程在写入文件的时候,读线程同时去读取,数据可能不一致。所以需要使用互斥锁(mutex)来保证同一时间只有一个线程访问文件资源。 然后,我需要确定文件操作的函数。读线程可能用fread,写线程用fwrite,或者使用更底层的read和write系统调用。不过为了简化示例,使用标准库的fopen、fread、fwrite可能更合适,但要注意这些函数是否是线程安全的。不过当配合互斥锁使用时,可以确保线程安全。 接下来,结构设计。主函数里创建两个线程,一个执行读函数,一个执行写函数。需要传递文件指针给这两个线程,或者让它们通过全局变量访问同一个文件指针。不过使用全局变量的话,更方便互斥锁的管理。因此,可能在全局定义文件指针和互斥锁。 然后,线程函数的结构。读线程会循环读取文件内容,每次读取前加锁,读取后解锁。同样,写线程在写入时也要加锁。需要注意的是,文件打开模式,比如读写线程可能需要以追加模式打开,或者读写模式,这取决于具体需求。用户没有说明具体需求,可能默认使用读写模式,但要注意如果同时读写,可能需要用"r+"或"w+"等模式,但可能会覆盖内容。这里可能需要更明确的说明,但示例中可能采用读线程和写线程分别以读和追加的方式打开文件,或者使用同一个文件指针。 不过,如果两个线程使用同一个文件指针,那么读和写的位置可能会互相影响,比如写操作改变了文件指针的位置,导致读的位置出错。所以或许更好的做法是让读线程以只读方式打开文件,写线程以追加方式打开,这样两者互不干扰,但需要处理文件内容的变化。但这样可能涉及到文件同步的问题,比如写线程写入的内容是否会被读线程立即读取到。这可能比较复杂,但作为示例,可能采用简单的互斥锁保护文件访问,而不管具体文件指针的位置,或者每次操作前都重新定位文件指针。 或者,考虑到示例的简单性,可以让读线程和写线程分别操作不同的文件,或者交替读写同一个文件,但需要互斥锁来确保操作原子性。不过用户的问题是两个线程进行文件读写,可能是指一个读一个写,针对同一个文件。这时候需要注意文件打开的方式,比如读写线程需要以可读写的方式打开,并且使用互斥锁来同步访问。 综合这些因素,我需要编写一个示例,其中主线程创建两个线程,一个读,一个写,共享同一个文件指针,使用互斥锁保护文件操作。文件读写模式打开,例如"r+",这样既可以读也可以写。但需要注意每次写入后可能需要fflush,或者使用fseek来定位读写位置,避免冲突。 例如,写线程每次写入数据时,先加锁,写入到文件末尾,然后解锁。读线程则加锁,读取全部内容,然后解锁。但这样可能会导致读线程读取到旧数据,如果写线程还没有写入新内容的话。或者,可能需要更复杂的同步机制,比如条件变量,但为了示例的简洁,可能仅使用互斥锁,而不同步数据的内容,只保证操作的原子性。 现在,考虑代码的结构。全局变量定义文件指针和互ex锁。主函数初始化锁,打开文件,创建线程,等待线程结束,然后关闭文件和销毁锁。读线程函数循环读取文件内容,每次读取前加锁,读取后解锁。写线程函数循环写入数据,同样加锁解锁。 可能存在的问题:如果文件很大,读线程一次性读取全部内容可能效率低,但示例中可以简化处理,每次读取固定大小的数据。或者,读线程每次读取一行或固定长度,写线程每隔一段时间写入数据。 另外,线程函数需要是void*类型的参数和返回类型,所以可能需要将参数强制转换。例如,传递文件名给线程函数,或者使用全局变量。 不过,用户可能希望两个线程操作同一个文件,因此全局变量可能更方便。例如: FILE *fp; pthread_mutex_t mutex; 然后,在main函数中初始化mutex,打开文件,创建线程。读线程函数里,循环中加锁,读取文件内容,打印,然后解锁。写线程函数里,循环中加锁,写入数据,解锁。 但需要注意,如果文件以"w"模式打开,会清空内容,所以应该以"a+"或"r+"模式打开,允许读写,并且追加写入。例如,使用"a+"模式,这样写操作总是在文件末尾,而读操作可以从头开始。不过,在读取的时候可能需要fseek到开头,或者在写入后fflush,以确保数据被写入磁盘。 此外,示例中可能需要让写线程写入一些数据,而读线程读取并打印。比如,写线程每隔一秒写入一个字符串,读线程每隔两秒读取并打印内容。但为了示例的简单性,可能只进行一次或几次循环。 现在,将这些思路转化为代码。编写代码示例时,需要注意错误检查,比如文件是否成功打开,互斥锁是否成功初始化,线程是否成功创建等。但为了代码的简洁,示例中可能省略部分错误处理,但实际应用中应该加上。 例如,代码的大致结构: #include <stdio.h> #include <pthread.h> FILE *fp; pthread_mutex_t mutex; void* read_thread(void* arg) { char buffer[1024]; while (/* 条件 */) { pthread_mutex_lock(&mutex); // 读取文件内容 fseek(fp, 0, SEEK_SET); while (fgets(buffer, sizeof(buffer), fp) != NULL) { printf("Read: %s", buffer); } pthread_mutex_unlock(&mutex); sleep(1); } return NULL; } void* write_thread(void* arg) { int count = 0; while (count++ < 5) { pthread_mutex_lock(&mutex); fprintf(fp, "Message %d\n", count); fflush(fp); // 确保数据写入文件 pthread_mutex_unlock(&mutex); sleep(2); } return NULL; } int main() { pthread_t t1, t2; fp = fopen("test.txt", "a+"); if (fp == NULL) { perror("打开文件失败"); return 1; } pthread_mutex_init(&mutex, NULL); pthread_create(&t1, NULL, read_thread, NULL); pthread_create(&t2, NULL, write_thread, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); fclose(fp); pthread_mutex_destroy(&mutex); return 0; } 这个示例中,写线程每隔2秒写入一个消息,读线程每隔1秒尝试读取文件内容。使用互斥锁确保读写操作不会同时进行。读线程在读取前使用fseek定位到文件开头,以获取最新写入的内容。写线程使用"a+"模式打开文件,因此每次写入都是在文件末尾追加,并且使用fflush确保数据立即写入文件而不是留在缓冲区。 但需要注意的是,如果读线程在写线程未写入时读取,可能会重复读取旧数据,或者没有新数据时输出为空。这可能需要在代码中加入更多的逻辑,比如检查文件是否有新内容,但为了示例的简洁,可能不做处理。 此外,编译时需要链接pthread库,即使用命令gcc -o program program.c -lpthread。 用户可能需要这样的示例,所以需要检查代码是否有语法错误,比如是否正确使用互斥锁函数,是否正确处理文件指针等。例如,pthread_mutex_lock和unlock是否正确配对,文件是否以正确的模式打开等。 最后,根据用户的要求,生成相关问题,比如关于性能优化、同步机制、错误处理等。</think>以下是用C语言实现两个线程分别进行文件读写的代码示例及说明: ### C语言多线程文件读写实现 ```c #include <stdio.h> #include <pthread.h> #define FILENAME "shared.txt" // 全局互斥锁 pthread_mutex_t file_mutex = PTHREAD_MUTEX_INITIALIZER; void* reader_thread(void* arg) { char buffer[256]; FILE* fp = fopen(FILENAME, "r"); while (1) { pthread_mutex_lock(&file_mutex); // 加锁 if (fgets(buffer, sizeof(buffer), fp)) { printf("读取内容: %s", buffer); } rewind(fp); // 重置文件指针到开头 pthread_mutex_unlock(&file_mutex); // 解锁 sleep(1); } fclose(fp); return NULL; } void* writer_thread(void* arg) { FILE* fp = fopen(FILENAME, "a"); int counter = 0; while (counter < 5) { pthread_mutex_lock(&file_mutex); // 加锁 fprintf(fp, "写入数据: %d\n", ++counter); fflush(fp); // 强制写入磁盘 pthread_mutex_unlock(&file_mutex); // 解锁 sleep(2); } fclose(fp); return NULL; } int main() { pthread_t t1, t2; // 初始化空文件 FILE* init = fopen(FILENAME, "w"); fclose(init); pthread_create(&t1, NULL, reader_thread, NULL); pthread_create(&t2, NULL, writer_thread, NULL); pthread_join(t2, NULL); pthread_cancel(t1); // 终止持续读取的线程 pthread_mutex_destroy(&file_mutex); return 0; } ``` #### 代码要点说明: 1. 使用`pthread_mutex_t`实现线程同步,保证读写操作的原子性[^1] 2. 写线程以追加模式("a")打开文件,确保写入位置正确 3. 读线程使用`rewind()`重置文件指针,读取最新内容 4. `fflush()`强制刷新缓冲区,保证数据持久化 5. 主线程创建前初始化空文件,避免读取异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值