精华内容
下载资源
问答
  • 智能指针在 标头文件的 std 命名空间中定义。 它们对 RAII 或 获取资源即初始化 编程惯用法至关重要。 RAII 的主要原则是为所有堆分配资源提供所有权,例如动态分配内存或系统对象句柄、析构函数包含要删除或释放...
  • 从点阵字库txt取字,指向文件内容位置的文件指针是唯一的,无法多个副本分别定位(无法一个文件使用多个指针),这与传统上内存中的指针不同。

    一、导言

    C语言中文件读写也是相当重要的一块,在进行二进制文件逐字节读写时,使用C语言会异常好用。文件指针也是个让人抓脑袋的东西,移动文件指针的函数利用好可以有大作用。

    二、操作

    1. 文件
      文件结构体定义在 stdio.h 头文件中,使用fopen打开文件后会存储一些相关数据在结构体中。
    typedef struct
    {
       short level;
       unsigned flags;
       char fd;
       unsigned char hold;
       short bsize;
       unsigned char *buffer;
       unsigned ar *curp;
       unsigned istemp;
       short token;
    }FILE;
    
    1. 文件指针操作
      文件指针操作主要有以下几个函数,在进行地址偏移计算时用得到。
      void rewind(FILE *stream); - 设置文件位置为给定流 stream 的文件的开头。
      long int ftell(FILE *stream); - 返回给定流 stream 的当前文件位置。
      int fseek(FILE *stream, long int offset, int whence); - 设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。

    三、实战

    目标:从点阵字库LiShu56.txt文件中提取某一个汉字。
    实现思路:通过汉字的gb2312机内码直接定位到文件中的该汉字起始位置,然后进行循环读写复制。
    字库文件格式截图示例
    上图即该文件中的格式,为图方便,我直接使用二进制文件查看器,定义了几个基本的偏移量。

    #define OFFSET_BASE 98      // 文件首基准位置
    #define OFFSET_WORD 3666    // 这是点阵字库中每个字的整体字节量
    #define OFFSET_INNER 13     // 这是单个字内部起始到实际字的数据的位置的偏移量
    

    因为该字库文件中收录的字并不是直接从 a1a1 连续到 f7fe 的,所以不能够直接求偏移量然后直接偏移,否则使用 fseek 偏移超过文件指针允许的范围,程序将会陷入卡死(或死循环)的状态。
     
    以下为算法流程图:
    偏移算法流程图
    注释:

    1. OFFSET_BASE 是从文件首到能够读取第一个(CurCode后)gb2312码的位置的偏移量。
    2. OFFSET_WORD 是读完这一gb2312码后到下一个字能够读取gb2312码的位置的偏移量。
    3. OFFSET_INNER 是找到该字后,从读完这一gb2312码的位置到能够读取点阵文本的首位置的偏移量。

    实现代码:
    该文件基于Windows系统,在Windows系统中中文占用为两个字节(char),在Linux系统中为三个字节。

    // 给单个字定位到指定位置
    FILE* locateChar(char* text, FILE* src)
    {
    	FILE* file = src;
    	fseek(file, OFFSET_BASE, SEEK_SET);		// 设置起始位置
    	char reader[5];
    	char gbk[5];
    	getGBK(gbk, text);		// 将汉字 text 的gbk码转为文本存储在gbk字符数组中
    	reader[4] = 0;
    	size_t size = sizeof(char);
    	for (int i = 0; i < 8178; i++)		// 该字库收录了8178个简体汉字
    	{
    		fread(reader, size, 4, file);
    		if (strcmp(reader, gbk) == 0)
    		{
    			printf("Found char %s\n", reader);
    			fseek(file, OFFSET_INNER, SEEK_CUR);
    			break;
    		}
    		else
    		{
    			fseek(file, OFFSET_WORD, SEEK_CUR);
    		}
    	}
    	return file;
    }
    

    定位到汉字所在位置后就可以进行读取复制操作了。

    	FILE* file = fopen("bitmap.txt", "wb+");
    	FILE* src = fopen("LiShu56.txt", "rb");
    	src = locateChar(word, src);	// 定位汉字
    	int tick = 56 * 56, flag;		// 该字库点阵尺寸为 56×56,flag用于标记跳出循环
    	size_t size = sizeof(char);
    	char reader;
    	while (tick)
    	{
    		flag = 0;
    		while (fread(&reader, size, 1, src))
    		{
    			switch (reader)
    			{
    			case '_': case 'X':
    				fwrite(&reader, size, 1, file);
    				tick--;
    				break;
    			case '\r':
    				fwrite(&reader, size, 1, file);
    				break;
    			case '\n':
    				fwrite(&reader, size, 1, file);
    				flag = 1;
    				break;
    			default: break;
    			}
    			if (flag) break;
    		}
    	}
    	fclose(src);
    	fclose(file);
    

    生成输出汉字“洋”示例:
    命令窗口输出

    Found char d1f3

    文件输出
    输出文本
     
    如果要将多个字合成在一个文件中,只需要稍作改动。
    不过注意,将 FILE* 赋值给多个变量分别进行 fseek 定位,然后两个指针这里读几个字符,那里读几个字符,最后你会发现每个文件指针指向的都是最后一次调用 fseek 定位的那个字,导致最后是好几个一样的字合在一起。比如我要合成“洋伊”,最后得到的是:

    Found char d1f3
    Found char d2c1
    出错示例

    抽象点说,简而言之,就是指向文件内容位置的文件指针是唯一的。
     
    如果要将多个字合成在一个文本中,可以采用以下思路:
    先将要合成的字,每个字存在一个临时文件中,再依次打开这些文件,读取并复制到(合成)同一文件中。
     

    四、附录

    示例代码中引用的部分函数代码

    // 获得十六进制对应字符
    char getX(int value)
    {
    	if (value < 10) return '0' + value;
    	else return 'a' + (value - 10);
    }
    
    // 直接获得文本GBK十六进制机内码
    void getGBK(char* dest, char* text)
    {
    	int value = (int)((unsigned char)text[0] * 256) + (int)(unsigned char)text[1];
    	int index = 3;
    	while (value)
    	{
    		dest[index--] = getX(value % 16);
    		value /= 16;
    	}
    	dest[4] = 0;
    }
    
    展开全文
  • Python 文件打开,关闭,文件指针

    千次阅读 2018-10-19 11:42:14
    python 文件操作 本章所讲内容: 10.1 文件对象 10.2 文件权限 10.3 文件操作 10.4 os 模块 10.1 文件对象 10.1.1 文件介绍 什么是文件? 示例如下: 狭义说:文本文件;广义说:超文本文件, 图片,...

     

    python 文件操作

    10.1 文件对象

    10.1.1  文件介绍

    10.1.2  文件的作用

    10.2  文件权限

    10.3  对文件的操作

    10.3.1  文件读取(面试题)

    10.3.3  指针

    10.3.4  实战

    10.4.1  Python系统路径和其他一些操作模块


    10.1   文件对象

    10.1.1  文件介绍

    什么是文件?

    示例如下:

                     

    狭义说:文本文件;

    广义说:超文本文件, 图片,声音,超链接,视频

    Python中可以使用一个文件对象,来做大部分文件操作,想要读取或写入文件,必须使用python内置的open()函数来打开它,该函数创建一个文件对象,这将用来调用与之关联的其他支持方式。

    语法File object = open(path,mode,[buffering])

    path:文件路经: 前期的时候我们写成固定的(绝对和相对路经),也可以使用os模块来辅助完成

    mode:权限:,r(read)读权限,w(write)写权限,a(add)追加写

    buffering:用于设置缓冲策略的可选整数,缓冲策略包括以下几种类型

    0:表示关闭缓冲(仅在二进制模式下允许)

    1:选择行缓冲(仅在文本模式下可用),类似命令提示符操作,当按下回车键后,缓冲结束,将回车符前面的内容交给系统进行处理后返回结果。

    >1的整数:表示将缓冲区设置为该整数大小。没有参数给定时,执行如下策略:二进制文件的缓冲区大小取决于系统底层设备和操作系统类型,一般情况下为4096或者8192字节长;交互式文本文件(isatty()返回True的文件)使用线路缓冲。其它文本文件使用二进制文件的策略

    10.1.2  文件的作用

    大家应该听说过一句话:“好记性不如烂笔头”。文件的作用一个字:存储并使用

                                                                                

    10.2    文件权限

    案例:open('1.txt','r')

    访问模式

    说明

    r

    以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。

    w

    打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

    a

    打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

    rb

    以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。

    wb

    以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

    ab

    以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

    r+

    打开一个文件用于读写。文件指针将会放在文件的开头。

    w+

    打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

    a+

    打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。

    rb+

    以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。

    wb+

    以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

    ab+

    以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

    文件对象的属性(方法):

    File.closed

    如果文件被关闭返回true,否则返回false

    File.mode

    返回文件被打开的访问模式

    File.name

    返回文件的名称

    f = open('1.txt','r',encoding='utf-8')
    #判断是否关闭
    print(f.closed)
    #打印权限
    print(f.mode)
    #打印文件的name
    print(f.name)
    #文件关闭
    f.close()
    

    10.3  对文件的操作

    10.3.1  文件读取(面试题

    1、遍历读取:文件对象本身可以迭代,并且以行的形式读取

    f = open('1.py','r',encoding='utf-8')
    #遍历进行读取
    for i in f:
        print(i)
    f.close()
    

    2、读取方法 :readn(),readline(),readlines()

           调用方法read()会一次性读取文件的全部内容,但是如果文件有10G,内存就爆了,会导致程序卡死,所以,要保险起见,可以反复调用read(size)方法,每次最多读取size个字符的内容。(注意这里是字符不是字节)

           另外,调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。

    f = open('1.py','r',encoding='utf-8')
    #读取所有内容
    # print(f.read(10))
    #读取一行
    # print(f.readline())
    #读取所有 并且按照list承载
    print(f.readlines())
    f.close()
    

    3、readline每次读取一行      

    4、readlines,一次性以行的形式读取文件的所有内容并返回一个list,需要去遍历读出来。

    10.3.2   写入文件

    1.   write 和 writelines

    f = open('2.txt','w',encoding='utf-8')
    # f.write('你好呀,hello,world')
    # f.writelines(str(i)+'\n' for i in range(10))
    f.writelines(['a','b','c'])
    f.close()
    

    两者的区别在哪呢?

    file.write(str)的参数是一个字符串,就是你要写入文件的内容。

    file.writelines(sequence)的参数是序列,比如列表,它会迭代帮你写入文件。

    3、close

    close()方法并关闭一个已经打开的文件对象,文件关闭后不能再执行读写操作。

    1、如果不去手动关闭文件,会一直占用我们的内存;

    2、关闭文件之后就不能对文件对象进行读写操作

    思考:如果读写文件出错,出现IOError的错误,我们后面的close()方法就不会调用,也就是说我们的文件就不会关闭,这个该如何?

    解决:

    1.  我们可以用异常处理来解决(但是每次这么写很繁琐),try 和 except 以及 finally在后面会讲到(先了解),打开已有的文件。

    try:
        f = open('1.txt', 'r',encoding='utf-8')
        print(f.read())
    except Exception as e:
        print(e)
    finally:
    # #启用关闭,不启用,两种情况
    #     f.close()
        pass
    # #用于判断是否关闭
    print(f.closed)

    2、with 语句实现自动关闭

    with open('2.txt','r',encoding='utf-8') as f:
        print(f.read())
    print(f.closed)
    

    with简单的导入原理(了解一下):

    1.  紧跟with后面的语句被求值后,返回对象的“__enter__()”方法被调用,这个方法的返回值将被赋值给as后面的变量;
    2.  当with后面的代码块全部被执行完之后,将调用前面返回对象的“__exit__()”方法。

    class A:
        def __enter__(self):
            print('__enter__() is called')
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('__exit__() is called ')
    with A() as a:
        print('got instance')
    

    运行结果如下:

    __enter__() is called

    got instance

    __exit__() is called
    3、对图片文件进行操作

    #对图片文件操作
    with open('for.png','rb') as png1:
        with open('shu.png','wb') as png2:
            png2.write(png1.read())
    #第二种(不推荐)
    with open('for.png','rb') as png1, open('shu.png','wb') as png2:
        png2.write(png1.read())
    

    图片要以二进制读和二进制写

    10.3.3  指针

             
    1.   tell() 方法返回文件的当前位置,即文件指针当前位置。

    语法

    #tell() 方法语法:fileObject.tell()
    f = open('1.txt','r+',encoding='utf-8')
    #查看文件名
    print(f.name)
    #读取一行
    line = f.readline()
    print(line)
    #获取当前文件指针的位置(字节)
    pos = f.tell()
    print('当前的位置%s'%pos)
    f.close()

    2.  seek()方法控制指针位置

    seek()方法用于移动文件读取指针到指定位置。

    seek()语法格式:fileObject.seek(offset[, whence])

    seek [siːk]: 寻找

    whence [wens]: 从何处;从哪里

    offset [ˈɒfset]: 抵消;弥补;补偿

    offset   移动的长度(字节)

    whence  相对位置;0从开头(默认),1从当前,2从末尾

    如果offset为负数,表示从后往前移动n个字节

    f = open('1.txt','r+',encoding='gbk')
    print(f.name)
    #赌气一行
    line = f.readline()
    print(line)
    f.seek(0,0)
    print(f.readline())
    #获取为你家指针当前的位置
    pos = f.tell()
    print('当前只针的位置%s'%pos)
    #关闭
    f.close()
    

    运行结果如下:

    1.txt

    当我还只有六岁的时候,在一本描写原始森林的名叫《真实的故事》的书中, 看到了一副精彩的插画,画的是一条蟒蛇正在吞食一只大野兽。页头上就是那副 画的摹本。

    当我还只有六岁的时候,在一本描写原始森林的名叫《真实的故事》的书中, 看到了一副精彩的插画,画的是一条蟒蛇正在吞食一只大野兽。页头上就是那副 画的摹本。

    当前只针的位置152

    10.3.4   实战电子书翻页功能

    分析:电子书现在有自动翻页功能(死循环,深度循环);有手动输入功能(在深度循环中加入判断条件);

    import time
    def reader(path,line = 3):
        #打开文件读取
        with open(path,'r',encoding='gbk') as f:
            #我们把指针指向文件的末尾
            f.seek(0,2)
            #告诉我文件末尾的指针的位置总字节量
            end = f.tell()
            #指针指向开头
            f.seek(0,0)
            #你是否要开启自动?
            auto = input('是否开启自动:(y/n)?')
            if auto == 'y':#是
                while True:#深度循环
                    #循环三次 读取三行
                    for i in range(line):
                        print(f.readline())
                    time.sleep(2)#美都区三行会sleep2两秒
                    # 判断如果你的文件指针指向文件末尾 我就强制break
                    if f.tell() == end:
                        break
            else:
                con = 'N'
                f.seek(0,2)
                end = f.tell()
                f.seek(0,0)
                while True:
                    if con == 'N':
                        for i in range(line):
                            print(f.readline())
                    else:
                        print('请输入N')
                    if f.tell() == end:
                        break
                    con = input('>>>')
    reader('1.txt')

    运行结果如下:

    是否开启自动:(y/n)?n

     当我还只有六岁的时候,在一本描写原始森林的名叫《真实的故事》的书中, 看到了一副精彩的插画,画的是一条蟒蛇正在吞食一只大野兽。页头上就是那副 画的摹本。

    这本书中写道:“这些蟒蛇把它们的猎获物不加咀嚼地囫囵吞下,尔后就不 能再动弹了;它们就在长长的六个月的睡眠中消化这些食物。”

    >>>N

    10.4.1  Python系统路径和其他一些操作模块

    os常用功能

    os.sep

    符合当前系统的路径分割符,Linux/windows\

    os.name

    返回操作系统类型windows“nt”Linux“posix”

    os.rename

    更改文件名,传递两个参数(旧文件名,新文件名)

    os.getcwd

    返回当前的工作目录

    os.listdir

    列出指定目录下的目录和文件

    os.chdir

    修改当前的工作路径

    os.mkdir

    创建目录

    os.makedirs

    递归创建目录

    os.remove

    删除文件

    os.rmdir

    删除文件夹(文件夹下内容为空)

    os.removedirs

    递归删除文件夹

    os.system

    执行系统命令

    os.popen

    执行系统命令,会将结果以文件的形式返回

    os.walk

    通过在目录树中游走输出在目录中的文件名,向上或者向下

    os.path.join

    连接目录和文件名。os.path.join(path,name)

    os.path. isfile

    判断指定对象是否为文件。是返回True,否则False

    os.path.isdir

    判断指定对象是否为目录。是True,否则False

    os.path. split

    返回路径的目录和文件名

    os.path. exists

    检验指定的对象是否存在。是True,否则False

    os.path.getsize

    获取指定对象的文件大小

    os.path.abspath

    获得绝对路径

    os.path.basename

    返回文件名

    os.path.dirname

    返回文件所在目录

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    1.   os.name()——判断现在正在实用的平台,Windows 返回 ‘nt'; Linux 返回’posix'

     rename(需要修改的文件名, 新的文件名) 也可以做剪切。

    2.    os.getcwd()——得到当前工作的目录。

    3.    os.listdir()——指定所有目录下所有的文件和目录名,以列表的形式全部列举出来,其中没有区分目录和文件。

    4.    os.mkdir()——创建目录&os.makedirs(‘a/b/c’)递归创建目录。

    5.    os.remove()——删除指定文件

    6.    os.rmdir()——删除指定目录(该目录不能为空)注意:这样只能建立一层,要想递归建立可用:os.makedirs(‘x/y/z’)

    7.    os.path.isfile()——判断指定对象是否为文件。是返回True,否则False

    >>>os.path.isfile(‘1.txt’)

    True    

    8.   os.path.isdir()——判断指定对象是否为目录。是True,否则False。例

    >>>os.path.isdir(‘1.txt’)

    False    

    9.   os.path.exists()——检验指定的对象是否存在。是True,否则False.例:

    >>>os.path.exists(‘1.txt’)

    True    

    10.   os.path.split()——返回路径的目录和文件名。

    此处只是把前后两部分分开而已。就是找最后一个'/'。看例子:

    os.path.split('E:/xuegod/python3')

    ('E:/xuegod', 'python3')

    11.   os.getcwd()——获得当前工作的目录(get current work dir)

    12.   os.system()——执行shell命令。

    13.   os.chdir()——改变目录到指定目录(谨慎更改

    案例:
    os.getcwd()

    import os
    print('返回的本地路径为:',os.getcwd())
    path = './xuegod/'
    #修改本地路径
    os.chdir(path)
    print('新的本地路径为',os.getcwd())
    

    运行结果如下:

    E:\xuegod_code\1_12_异常处理

    E:\xuegod_code\1_12_异常处理\xuegod

    14. os.path.getsize()——获得文件的大小(字节),如果为目录,返回0

    >>>os.path.getsize('1.txt')

    1644

    15. os.path.abspath()——获得绝对路径。

    print(os.path.abspath('1.txt'))
    运行结果如下:
    E:\xuegod_code\1_12_异常处理\1.txt
    

    16. os.path.join(path, name)——连接目录和文件名。

    import os
    file_path = os.getcwd()
    new_path = os.path.join(file_path,'1.txt')
    print(new_path)
    运行结果如下:
    E:\xuegod_code\1_12_异常处理\1.txt
    

    17.os.path.basename(path)——返回文件名

    18. os.path.dirname(path)——返回文件所在目录

    19. os.walk() 方法是一个简单易用的文件、目录遍历器,可以帮助我们高效的处理文件、目录方面的事情。在Unix,Windows中有效。

    表达式:

    os.walk(top[, topdown=True[, οnerrοr=None[, followlinks=False]]])

    top 代表的是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files)。

    root 所指的是当前正在遍历的这个文件夹的本身的地址。

    dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)。

    files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)。

    案例:

    import os
    #获取当前路径
    path = os.getcwd()
    #返回文件夹本身的地址,目录,文件
    for root,dirs,files in os.walk(path):
        for filename in files:
            print(os.path.join(root,filename))
    运行结果如下:
    E:\workspace\importTest\1.png
    E:\workspace\importTest\1.txt
    E:\workspace\importTest\2.png
    E:\workspace\importTest\2.py
    ……
    

    10.4.2 如何批量修改文件夹下的文件名?

    import os
    m_name = os.listdir('./xuegod/')
    #对该目录下的文件遍历
    for temp in m_name:
        #新的文件名
        new_name = 'xuegod'+temp
        #更改文件名,前参数 代表老文件名,后面的参数代表新的文件名
        os.rename('./xuegod/'+temp,'./xuegod/'+new_name)
    

          

    11.4.3  实战:获取文件绝对路径
    传入一个文件路径,得到该路径下所有的文件的绝对路径?(面试题)
    import os
    def iterbrowse(path):
        #返回路径,目录,文件;
        for home,dirs,files in os.walk(path):
            #对文件进行遍历
            for file in files:
                #拼接路径和name
                print(os.path.join(home,file))
    #处理当前的文件路径
    new_path = os.getcwd()
    #调用
    iterbrowse(new_path)
    输出结果如下:
    E:\workspace\importTest\9_1_write_test.py
    E:\workspace\importTest\9_2_with_test.py
    E:\workspace\importTest\9_3_with_test02.py
    E:\workspace\importTest\9_4_tell_test.py
    E:\workspace\importTest\9_5_shizhan.py
    E:\workspace\importTest\9_6_os_test.py
    E:\workspace\importTest\class_test.py
    E:\workspace\importTest\class_test01.py
    ……
    

     

    展开全文
  • 【C++】文件读写指针定位

    千次阅读 2020-06-30 09:09:41
    主要函数:指针定位函数SetFilePointer,读文件ReadFile,写文件WriteFile。 首先使用CreateFile创建文件,SetFilePointer函数将指针定位到文件指定位置(tail),从这个位置开始调用WriteFile函数写入内容(text)...

    主要函数:指针定位函数SetFilePointer,读文件ReadFile,写文件WriteFile
    首先使用CreateFile创建文件,SetFilePointer函数将指针定位到文件指定位置(tail),从这个位置开始调用WriteFile函数写入内容(text);同理可将指针定位到指定位置,从这个位置开始调用ReadFile函数读取指定长度的内容。

    #include<iostream>
    #include<string>
    #include <fstream>
    using namespace std;
    
    int main() {
    	const char* path = "temp.txt";
    	HANDLE hFile = CreateFile(
    		path,
    		GENERIC_WRITE | GENERIC_READ,
    		FILE_SHARE_READ,
    		NULL,
    		OPEN_ALWAYS,
    		FILE_ATTRIBUTE_NORMAL,
    		NULL);
    	if (hFile == INVALID_HANDLE_VALUE){
    		cout << ("create file failed./n");
    		return -1;
    	}
    	// 分配文件空间
    	SetFilePointer(hFile, 2 * 1024 * 1024 - 1, NULL, FILE_BEGIN); //*1024
    	SetEndOfFile(hFile);
    
    	/*写文件*/
    	int tail = 0;
    	DWORD dwR;
    	char text[] = "test file";
    	/*指针移动到tail位置*/
    	SetFilePointer(hFile, tail, NULL, FILE_BEGIN);
    	WriteFile(hFile, text, strlen(text), &dwR, NULL);
    	tail = tail + strlen(text);
    	cout << "当前tail位置 " << tail << endl;
    
    	/*读文件*/
    	char* read = new char[strlen(text) + 1];
    	int pos = 0, length = 6;
    	cout << "从 " << pos << " 位置开始读取文件,长度为" << length << endl;
    	SetFilePointer(hFile, pos, NULL, FILE_BEGIN);
    	ReadFile(hFile, read, length, &dwR, NULL);
    	read[length] = '\0';
    	cout << read << endl;
    }
    
    展开全文
  • C语言文件操作一

    千次阅读 多人点赞 2019-11-04 20:58:15
    在C语言中,操作文件之前必须先打开文件,所谓“打开文件”,就是让程序和文件建立连接的过程。 打开文件之后,程序可以得到文件的相关信息,例如大小、类型、权限、创建者、更新时间等。在后续读写文件的过程中,...

    C语言文件操作介绍

    在C语言中,操作文件之前必须先打开文件,所谓“打开文件”,就是让程序和文件建立连接的过程。

    打开文件之后,程序可以得到文件的相关信息,例如大小、类型、权限、创建者、更新时间等。在后续读写文件的过程中,程序还可以记录当前读写到了哪个位置,下次可以在此基础上继续操作。

    使用 <stdio.h> 头文件中的 fopen() 函数即可打开文件,它的用法为:

    FILE *fopen(char *filename, char *mode);
    

    filename 为文件名(包括文件路径),mode为打开方式,它们都是字符串。

    fopen() 函数的返回值

    fopen() 会获取文件信息,包括文件名、文件状态、当前读写位置等,并将这些信息保存到一个 FILE 类型的结构体变量中,然后将该变量的地址返回。

    FILE 是 <stdio.h> 头文件中的一个结构体,它专门用来保存文件信息。我们不用关心 FILE 的具体结构,只需要知道它的用法就行。

    FILE *fp = fopen("demo.txt", "r");
    

    表示以“只读”方式打开当前目录下的 demo.txt 文件,并使 fp 指向该文件,这样就可以通过 fp 来操作 demo.txt 了。fp 通常被称为文件指针

    再来看一个例子:

    FILE *fp = fopen("D:\\demo.txt","rb+");
    

    表示以二进制方式打开 D 盘下的 demo.txt 文件,允许读和写。


    判断文件是否打开成功

    打开文件出错时,fopen() 将返回一个空指针,也就是 NULL,我们可以利用这一点来判断文件是否打开成功,请看下面的代码:

    FILE *fp;
    if( (fp=fopen("D:\\demo.txt","rb") == NULL ){
        printf("Fail to open file!\n");
        exit(0);  //退出程序(结束程序)
    }
    

    以上代码是文件操作的规范写法,读者在打开文件时一定要判断文件是否打开成功,因为一旦打开失败,后续操作就都没法进行了,往往以“结束程序”告终。
    在这里插入图片描述
    调用 fopen() 函数时必须指明读写权限,但是可以不指明读写方式(此时默认为"t")。

    读写权限和读写方式可以组合使用,但是必须将读写方式放在读写权限的中间或者尾部(换句话说,不能将读写方式放在读写权限的开头)。例如:

    将读写方式放在读写权限的末尾:“rb”、“wt”、“ab”、“r+b”、“w+t”、“a+t”
    将读写方式放在读写权限的中间:“rb+”、“wt+”、“ab+”


    关闭文件

    文件一旦使用完毕,应该用 fclose() 函数把文件关闭,以释放相关资源,避免数据丢失。

    fclose() 的用法为:

    int fclose(FILE *fp);
    

    fp 为文件指针。例如:
    fclose(fp);
    文件正常关闭时,fclose() 的返回值为0,如果返回非零值则表示有错误发生。

    通过一段代码来体会文件操作

    #include <stdio.h>
    #include <stdlib.h>
    #define N 100
    int main() {
        FILE *fp;
        char str[N + 1];
        //判断文件是否打开失败
        if ( (fp = fopen("d:\\demo.txt", "rt")) == NULL ) {
            puts("Fail to open file!");
            exit(0);
        }
        //循环读取文件的每一行数据
        while( fgets(str, N, fp) != NULL ) {
            printf("%s", str);
        }
       
        //操作结束后关闭文件
        fclose(fp);
        return 0;
    }
    

    对于 Windows 平台,为了保险起见,我们最好用"t"来打开文本文件,用"b"来打开二进制文件。对于 Linux 平台,使用"r"还是"b"都无所谓,既然默认是"r",那我们什么都不写就行了


    字符读取函数 fgetc与字符写入函数fputc

    fgetc() 的用法为:

    int fgetc (FILE *fp);
    

    fp 为文件指针。fgetc() 读取成功时返回读取到的字符,读取到文件末尾或读取失败时返回EOF。

    EOF 是 end of file 的缩写,表示文件末尾,是在 stdio.h 中定义的宏,它的值是一个负数,往往是 -1。fgetc() 的返回值类型之所以为 int,就是为了容纳这个负数(char不能是负数)。

    用法举例:

    char ch;
    FILE *fp = fopen("D:\\demo.txt", "r+");
    ch = fgetc(fp);
    

    在文件内部有一个位置指针,用来指向当前读写到的位置,也就是读写到第几个字节。在文件打开时,该指针总是指向文件的第一个字节。使用 fgetc() 函数后,该指针会向后移动一个字节,所以可以连续多次使用 fgetc() 读取多个字符。

    案例:

    
    #include<stdio.h>
    int main(){
        FILE *fp;
        char ch;
      
        //如果文件不存在,给出提示并退出
        if( (fp=fopen("D:\\demo.txt","rt")) == NULL ){
            puts("Fail to open file!");
            exit(0);
        }
        //每次读取一个字节,直到读取完毕
        while( (ch=fgetc(fp)) != EOF ){
            putchar(ch);
        }
        putchar('\n');  //输出换行符
        if(ferror(fp)){
            puts("读取出错");
        }else{
            puts("读取成功");
        }
        fclose(fp);
        return 0;
    

    fputc() 的用法为:

    int fputc ( int ch, FILE *fp );
    

    ch 为要写入的字符,fp 为文件指针。fputc() 写入成功时返回写入的字符,失败时返回 EOF,返回值类型为 int 也是为了容纳这个负数。例如:
    fputc(‘a’, fp);
    或者:
    char ch = ‘a’;
    fputc(ch, fp);
    表示把字符 ‘a’ 写入fp所指向的文件中。


    fgets和fputs函数

    fgetc() 和 fputc() 函数每次只能读写一个字符,速度较慢;实际开发中往往是每次读写一个字符串或者一个数据块,这样能明显提高效率。

    读字符串函数 fgets
    fgets() 函数用来从指定的文件中读取一个字符串,并保存到字符数组中,它的用法为:

    char *fgets ( char *str, int n, FILE *fp );
    

    str 为字符数组,n 为要读取的字符数目,fp 为文件指针。

    返回值:读取成功时返回字符数组首地址,也即 str;读取失败时返回 NULL;如果开始读取时文件内部指针已经指向了文件末尾,那么将读取不到任何字符,也返回 NULL。

    注意,读取到的字符串会在末尾自动添加 ‘\0’,n 个字符也包括 ‘\0’。也就是说,实际只读取到了 n-1 个字符,如果希望读取 100 个字符,n 的值应该为 101

    需要重点说明的是,在读取到 n-1 个字符之前如果出现了换行,或者读到了文件末尾,则读取结束。这就意味着,不管 n 的值多大,fgets() 最多只能读取一行数据,不能跨行。在C语言中,没有按行读取文件的函数,我们可以借助 fgets(),将 n 的值设置地足够大,每次就可以读取到一行数据。

    例:

    #include <stdio.h>
    #include <stdlib.h>
    #define N 100
    int main(){
        FILE *fp;
        char str[N+1];
        if( (fp=fopen("d:\\demo.txt","rt")) == NULL ){
            puts("Fail to open file!");
            exit(0);
        }
       
        while(fgets(str, N, fp) != NULL){
            printf("%s", str);
        }
        fclose(fp);
        return 0;
    }
    

    fputs() 函数用来向指定的文件写入一个字符串,它的用法为:

    int fputs( char *str, FILE *fp );
    

    str 为要写入的字符串,fp 为文件指针。写入成功返回非负数,失败返回 EOF。
    例如:

    char *str = "http://c.biancheng.net";
    FILE *fp = fopen("D:\\demo.txt", "at+");
    fputs(str, fp);
    

    表示把字符串str写入到D://demo.txt文件中


    fread 和 fwrite

    fread() 函数用来从指定文件中读取块数据。所谓块数据,也就是若干个字节的数据,可以是一个字符,可以是一个字符串,可以是多行数据,并没有什么限制。fread() 的原型为:

    size_t fread ( void *ptr, size_t size, size_t count, FILE *fp );
    

    fwrite() 函数用来向文件中写入块数据,它的原型为:

    size_t fwrite ( void * ptr, size_t size, size_t count, FILE *fp );
    

    对参数的说明:

    • ptr 为内存区块的指针,它可以是数组、变量、结构体等。fread() 中的 ptr 用来存放读取到的数据,fwrite() 中的 ptr 用来存放要写入的数据。
    • size:表示每个数据块的字节数。
    • count:表示要读写的数据块的块数。
    • fp:表示文件指针。

    理论上,每次读写 size*count 个字节的数据。

    size_t 是在 stdio.h 和 stdlib.h 头文件中使用 typedef 定义的数据类型,表示无符号整数,也即非负数,常用来表示数量。

    返回值:返回成功读写的块数,也即 count。如果返回值小于 count:

    对于 fwrite() 来说,肯定发生了写入错误,可以用 ferror() 函数检测。
    对于 fread() 来说,可能读到了文件末尾,可能发生了错误,可以用 ferror() 或 feof() 检测。

    样例程序:从键盘输入两个学生数据,写入一个文件中,再读出这两个学生的数据显示在屏幕上。

    #include<stdio.h>
    #define N 2
    struct stu{
        char name[10]; //姓名
        int num;  //学号
        int age;  //年龄
        float score;  //成绩
    }boya[N], boyb[N], *pa, *pb;
    int main(){
        FILE *fp;
        int i;
        pa = boya;
        pb = boyb;
        if( (fp=fopen("d:\\demo.txt", "wb+")) == NULL ){
            puts("Fail to open file!");
            exit(0);
        }
        //从键盘输入数据
        printf("Input data:\n");
        for(i=0; i<N; i++,pa++){
            scanf("%s %d %d %f",pa->name, &pa->num,&pa->age, &pa->score);
        }
        //将数组 boya 的数据写入文件
        fwrite(boya, sizeof(struct stu), N, fp);
        //将文件指针重置到文件开头
        rewind(fp);
        //从文件读取数据并保存到数据 boyb
        fread(boyb, sizeof(struct stu), N, fp);
        //输出数组 boyb 中的数据
        for(i=0; i<N; i++,pb++){
            printf("%s  %d  %d  %f\n", pb->name, pb->num, pb->age, pb->score);
        }
        fclose(fp);
        return 0;
    }
    

    数据写入完毕后,位置指针在文件的末尾,要想读取数据,必须将文件指针移动到文件开头,这就是 rewind(fp) 的作用。


    fscanf 和 fprintf

    fscanf() 和 fprintf() 函数与前面使用的 scanf() 和 printf() 功能相似,都是格式化读写函数,两者的区别在于 fscanf() 和 fprintf() 的读写对象不是键盘和显示器,而是磁盘文件

    这两个函数的原型为:

    int fscanf ( FILE *fp, char * format, ... );
    int fprintf ( FILE *fp, char * format, ... );
    

    fp 为文件指针,format 为格式控制字符串,… 表示参数列表。与 scanf() 和 printf() 相比,它们仅仅多了一个 fp 参数。例如:

    FILE *fp;
    int i, j;
    char *str, ch;
    fscanf(fp, "%d %s", &i, str);
    fprintf(fp,"%d %c", j, ch);
    

    fprintf() 返回成功写入的字符的个数,失败则返回负数。fscanf() 返回参数列表中被成功赋值的参数个数。

    样例程序:用fscanf和fprintf函数来完成对学生信息读写

    #include<stdio.h>
    
    #define N 2
    
    struct stu{
        char name[10];
        int num;
        int age;
        float score;
    } boya[N], boyb[N], *pa, *pb;
    
    int main(){
        FILE *fp;
        int i;
        pa=boya;
        pb=boyb;
        if( (fp=fopen("D:\\demo.txt","wt+")) == NULL ){
            puts("Fail to open file!");
            exit(0);
        }
    
        //从键盘读入数据,保存到boya
        printf("Input data:\n");
        for(i=0; i<N; i++,pa++){
            scanf("%s %d %d %f", pa->name, &pa->num, &pa->age, &pa->score);   
        }
        pa = boya;
        //将boya中的数据写入到文件
        for(i=0; i<N; i++,pa++){
            fprintf(fp,"%s %d %d %f\n", pa->name, pa->num, pa->age, pa->score);   
        }
        //重置文件指针
        rewind(fp);
        //从文件中读取数据,保存到boyb
        for(i=0; i<N; i++,pb++){
            fscanf(fp, "%s %d %d %f\n", pb->name, &pb->num, &pb->age, &pb->score);
        }
        pb=boyb;
        //将boyb中的数据输出到显示器
        for(i=0; i<N; i++,pb++){
            printf("%s  %d  %d  %f\n", pb->name, pb->num, pb->age, pb->score);
        }
    
        fclose(fp);
        return 0;
    }
    

    如果将 fp 设置为 stdin,那么 fscanf() 函数将会从键盘读取数据,与 scanf 的作用相同;设置为 stdout,那么 fprintf() 函数将会向显示器输出内容,与 printf 的作用相同。例如:

    #include<stdio.h>
    int main(){
        int a, b, sum;
        fprintf(stdout, "Input two numbers: ");
        fscanf(stdin, "%d %d", &a, &b);
        sum = a + b;
        fprintf(stdout, "sum=%d\n", sum);
        return 0;
    }
    

    随机读写文件

    在实际开发中经常需要读写文件的中间部分,要解决这个问题,就得先移动文件内部的位置指针,再进行读写。这种读写方式称为随机读写,也就是说从文件的任意位置开始读写。

    实现随机读写的关键是要按要求移动位置指针,这称为文件的定位

    移动文件内部位置指针的函数主要有两个,即 rewind()fseek()

    rewind()用来将位置指针移动到文件开头,原型为:

    void rewind(FILE *fp);
    

    fseek()用来将位置指针移动到任意位置,它的原型为:

    int fseek ( FILE *fp, long offset, int origin );
    

    参数说明:

    1. fp 为文件指针,也就是被移动的文件。

    2. offset 为偏移量,也就是要移动的字节数。之所以为 long 类型,是希望移动的范围更大,能处理的文件更大。offset 为正时,向后移动;offset 为负时,向前移动。

    3. origin 为起始位置,也就是从何处开始计算偏移量。C语言规定的起始位置有三种,分别为文件开头、当前位置和文件末尾,每个位置都用对应的常量来表示:

    在这里插入图片描述

    例如,把位置指针移动到离文件开头100个字节处:

    fseek(fp, 100, 0);
    

    值得说明的是,fseek() 一般用于二进制文件,在文本文件中由于要进行转换,计算的位置有时会出错。

    例:
    在移动位置指针之后,就可以用前面介绍的任何一种读写函数进行读写了。由于是二进制文件,因此常用 fread() 和 fwrite() 读写。

    从键盘输入三组学生信息,保存到文件中,然后读取第二个学生的信息

    #include<stdio.h>
    #define N 3
    struct stu{
        char name[10]; //姓名
        int num;  //学号
        int age;  //年龄
        float score;  //成绩
    }boys[N], boy, *pboys;
    int main(){
        FILE *fp;
        int i;
        pboys = boys;
        if( (fp=fopen("d:\\demo.txt", "wb+")) == NULL ){
            printf("Cannot open file, press any key to exit!\n");
            getch();
            exit(1);
        }
        printf("Input data:\n");
        for(i=0; i<N; i++,pboys++){
            scanf("%s %d %d %f", pboys->name, &pboys->num, &pboys->age, &pboys->score);
        }
        fwrite(boys, sizeof(struct stu), N, fp);  //写入三条学生信息
        fseek(fp, sizeof(struct stu), SEEK_SET);  //移动位置指针
        fread(&boy, sizeof(struct stu), 1, fp);  //读取一条学生信息
        printf("%s  %d  %d %f\n", boy.name, boy.num, boy.age, boy.score);
        fclose(fp);
        return 0;
    }
    

    运行结果:
    Input data:
    Tom 2 15 90.5↙
    Hua 1 14 99↙
    Zhao 10 16 95.5↙
    Hua 1 14 99.000000

    展开全文
  • c++ 智能指针循环引用问题

    万次阅读 多人点赞 2014-04-07 13:36:05
    c++智能指针介绍 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete,比如流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有... 智能指针在 标头文件的 std 命名空间中定义
  • 尹成老师带你步入 C 语言的殿堂,讲课生动风趣、深入浅出,全套视频内容充实,整个教程以 C 语言为核心,完整精彩的演练了数据结构、算法、设计模式、数据库、大数据高并发检索、文件重定向、多线程同步、进程通讯、...
  • C使用FILE指针文件操作

    千次阅读 2018-08-01 20:34:36
    实际上在前面的各章中我们已经多次使用了文件,例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。文件通常是驻留在外部介质(如磁盘等)上的,在使用时才调入内存中来。从不同的角度可对文件作不同的分类。...
  • 文件指针问题

    千次阅读 2014-04-07 16:10:12
    文件指针是指向整个文件的,须在程序中定义说明,只要不重新赋值,文件指针的值是不变的。文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针均向后移动,它不需在程序中定义说明,而是由系统...
  • C语言指针详解

    千次阅读 多人点赞 2014-10-26 08:37:01
    指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。...
  • 指针文件fp的使用

    千次阅读 2014-05-25 16:03:39
    C使用FILE指针文件操作 文件 文件的基本概念  所谓“文件”是指一组相关数据的有序集合。 这个数据集有一个名称,叫做文件名。实际上在前面的各章中我们已经多次使用了文件,例如源程序文件、目标文件、...
  • 一、普通文件的读写 打开文件的步骤:打开 --> 操作 --> 关闭 ...-默认从文件指针所在位置开始写入 w: -只能写 -会清空文件之前的内容 -文件不存在,不会报错,会创建新的文件并写入 w...
  • C语言中file文件指针概念及其操作

    万次阅读 多人点赞 2014-01-06 09:16:15
    实际上在前面的各章中我们已经多次使用了文件,例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。文件通常是驻留在外部介质(如磁盘等)上的,在使用时才调入内存中来。从不同的角度可对文件作不同的分类。...
  • python文件处理指针的移动

    千次阅读 2018-11-27 17:21:00
    控制文件指针移动 with open('a.txt',mode='rt',encoding='utf-8')as f: res=f.read(4) print(res) 强调:只有t模式下read(n)中的n表示的是字符个数,其他都是以字节为单位。 with open('a.txt',mode...
  • //由于仅带尾指针的单循环链表尾指针不断变化, 所以只能传递地址,通过地址改变实参的值; PLinkQueue CreateLinkQueue(void); void DestroyLinkQueue(PLinkQueue * pR); bool EmptyLinkQueue(PLinkQueue * pR); ...
  • 循环链表和单链表(参考单链表)大致一样,只是尾结点要指向头结点,本文是使用尾结点rear来表示,之所以使用尾指针,是因为如果使用头结点来寻找列表最后一个元素时间复杂度为O(n),如果使用尾结点来寻找列表最后...
  • 准备写队列以下几种类型:循环队列(顺序结构),链队列,循环队列(只有尾指针),字符队列(顺序结构) 一、循环队列循环队列存储结构typedef int QElemType; typedef struct{ QElemType *base; int front; int...
  • 假设以带头结点的循环链表(看清楚了是链表,不是循环队列,小编一开始就看错了,浪费了挺多时间)表示队列,并且只设一个指针指向队尾元素结点(注意:不设头指针),试编写相应的置空队列、判断队列是否为空、入队和出...
  • 一、文件的输入输出 二、从txt文件中读取二维数组(int 以及string) 三、从txt文件读取的数据存到struct中 &amp;amp;nbsp; 一、文件的输入输出 1.fstream提供了三个类,用来实现c++对文件的操作。(文件的...
  • //将文件指针移到目标行的行首 fseek(fp,c,SEEK_SET); //得到目标行的长度 cnt=c1-c; //for循环插入想要修改的内容 for(i=0;i;i++) { fputc(' ',fp); } if(fclose(fp)==0) printf("文件关闭成功!\n"); ...
  • C语言使用FILE指针文件操作

    千次阅读 多人点赞 2018-08-25 20:59:30
    C语言使用FILE指针文件操作 文件的基本概念 所谓“文件”是指一组相关数据的有序集合。这个数据集有一个名称,叫做文件名。实际上我们已经多次使用了文件,例如源程序文件、目标文件、可执行文件、库文件(头文件...
  • C语言基于socket的文件传输(可循环发送多个文件)

    万次阅读 多人点赞 2018-07-10 10:32:57
    这是因为文件可能比较大,一个缓冲数组只能保存一部分文件内容,因此服务器得不断从文件中读取内容并发给客户端,而客户端得不停的循环接收。但是在事先,得将相应要发送的文件(照片,音频,视频等)保存在服务器相应...
  • 队列的顺序存储实现—循环队列

    千次阅读 2015-04-17 21:37:40
    循环队列是指队列的首尾两个指针可以绕着队列循环移动。例如,当往循环队列中添加元素(入队列)时,将队列的尾指针rear向后移动一步,如果其超出了队列的最大长度MAXSIZE则回绕到队列的头部继续;当从循环队列中取...
  • C语言

    万次阅读 多人点赞 2019-12-18 23:01:50
    循环队列中的元素个数随队头指针和队尾指针变化而动态变化。 6.C语言中的result只是一个自己定义的量 7.对空和队满时,头尾指针均相等。 8.冒泡法是在扫描过程中逐次比较相邻两个元素的大小。例:9+8+7+6+5+4+3+2+1=...
  • 我这里用的是CFile的getposition和getlength,它和CArchive对象操作的文件指针是一个指针么?还是这样并不能获得CArchive在文件内读写时的指针呢?如果是一个指针,为什么只能循环一次呢? 还有就是hi,上面我在最后...
  • inputFile = open('xiao.csv','r') line = inputFile.readline() #先初始化,指向文件头 while line: name = line.split(',')[6] ...#while循环结束后,指针文件末尾 inputFile.seek(0) #返回文件头 line
  • vs2019 开始自己的第一个C++程序

    万次阅读 多人点赞 2019-03-16 21:09:43
    点击菜单栏-->文件-->新建-->项目,我们可以看到上方存在的语言,平台和项目类型的选项 (1)语言这里我们就选择C++,或者所有语言 (2)平台这里我们就选择windows,或者所有平台 (3)项目类型这里选择控制台,...
  • 前天用java写了个小程序,用来遍历磁盘的文件,结果跳出来个NullPointException,一开始我以为是我程序的问题,找了半天没找出来错在了哪,当我把遍历的对象改成我的u盘时,程序运行正常,没有报出错误,感觉有点懵...
  • C语言全套资料 C语言程序设计 C语言算法 C语言课件 C语言顺序程序设计,C语言数组,C语言循环控制,C语言预处理命令,C语言文件操作指针,C语言选择结构程序设计,C语言结构体与共用体,C语言文件操作,C语言函数

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 247,407
精华内容 98,962
关键字:

文件指针循环