c#如何修改1万行的文本文件中某一行的某个字符串?或插入、删除某一行。

时间:2023-02-11 08:36:28
文本文件的格式如下:(有上万条)

刘一 = 111002
...
...
张三 = 10x1
李四 = 303232
王五 = 62410
...
...
 
1、修改或插入数据时,是否一定要先读取文本中所有的数据?能否读取一条,修改一条,然后保存,再读取下一条。
   如果是非要读出数据,那么1万或数万行是否就会容易导致内存溢出?
2、如何只更改其中某一行的比如,先找到"李四"的这一行,然后把"李四"后面等号的值"303232"改为"313232"?
3、在李四这一行后面插入 新的一行,并删除王五这一行的数据。

7 个解决方案

#1


这是一个用内存映射的方式来操作大文件,可以参考一下




using System.Runtime.InteropServices; 
  
 [DllImport("kernel32.dll")] 
 public static extern IntPtr CreateFileMapping(IntPtr hFile, 
     IntPtr lpFileMappingAttributes, uint flProtect, 
     uint dwMaximumSizeHigh, 
     uint dwMaximumSizeLow, string lpName); 
  
 [DllImport("kernel32.dll")] 
 public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint 
     dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, 
     IntPtr dwNumberOfBytesToMap); 
  
 [DllImport("kernel32.dll")] 
 public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); 
  
 [DllImport("kernel32.dll")] 
 public static extern bool CloseHandle(IntPtr hObject); 
  
 [DllImport("kernel32.dll")] 
 public static extern IntPtr CreateFile(string lpFileName,  
     int dwDesiredAccess, FileShare dwShareMode, IntPtr securityAttrs,  
     FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile); 
  
 [DllImport("kernel32.dll")] 
 public static extern uint GetFileSize(IntPtr hFile, IntPtr lpFileSizeHigh); 
  
 public const int GENERIC_READ = -2147483648; //0x80000000 
 public const int GENERIC_WRITE = 0x40000000; 
 public const int GENERIC_EXECUTE = 0x20000000; 
 public const int GENERIC_ALL = 0x10000000; 
 public const int FILE_ATTRIBUTE_NORMAL = 0x80; 
 public const int FILE_FLAG_SEQUENTIAL_SCAN = 0x8000000; 
 public const int INVALID_HANDLE_VALUE = -1; 
  
 public const int PAGE_NOACCESS = 1; 
 public const int PAGE_READONLY = 2; 
 public const int PAGE_READWRITE = 4; 
  
 public const int FILE_MAP_COPY = 1; 
 public const int FILE_MAP_WRITE = 2; 
 public const int FILE_MAP_READ = 4; 
  
  
 private void button1_Click(object sender, EventArgs e) 
 { 
     IntPtr vFileHandle = CreateFile(@"c:\temp\temp.txt", 
         GENERIC_READ | GENERIC_WRITE, FileShare.Read | FileShare.Write, 
         IntPtr.Zero,  FileMode.Open, 
         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, IntPtr.Zero); 
     if (INVALID_HANDLE_VALUE != (int)vFileHandle)  
     { 
         IntPtr vMappingHandle = CreateFileMapping( 
             vFileHandle, IntPtr.Zero, PAGE_READWRITE, 0, 0, "~MappingTemp"); 
         if (vMappingHandle != IntPtr.Zero) 
         { 
             IntPtr vHead = MapViewOfFile(vMappingHandle, 
                 FILE_MAP_COPY | FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, IntPtr.Zero); 
             if (vHead != IntPtr.Zero) 
             { 
                 uint vSize = GetFileSize(vFileHandle, IntPtr.Zero); 
                 for (int i = 0; i  <= vSize / 2; i++) 
                 { 
                     byte vTemp = Marshal.ReadByte((IntPtr)((int)vHead + i)); 
                     Marshal.WriteByte((IntPtr)((int)vHead + i), 
                         Marshal.ReadByte((IntPtr)((int)vHead + vSize - i - 1))); 
                     Marshal.WriteByte((IntPtr)((int)vHead + vSize - i - 1), vTemp); 
                 } 
                 UnmapViewOfFile(vHead); 
             } 
             CloseHandle(vMappingHandle); 
         } 
         CloseHandle(vFileHandle); 
     } 
 } 


 

#2


竟然有那么大的txt

#3


最好保存到新的文件中去。
除非你修改文件时不会影响后面的内容,也就是要修改的这一行比如占10个字节,修改后还要在此处填写10个字节

#4


1 楼太热情了

#5


最近有很多人喜欢提问 巨型文本文件搜索
为何放弃数据库用文本文档存数据?

#6


我记得用StreamReader,可以单个字符读取,也可以一性读取所有内容。所以针对你的问题,两种办法你可以根据效率自己选择一下,StreamReader读取返回是字符串string,应该不会有内在溢出的问题。文本文件中的制作转义符是\r\n。我觉得知道了这些信息做插入删除或修改都不难了,自己写一个处理类吧。

#7


顺带了 楼主818咋个去找系统的api函数嘛
以及功能调用

#1


这是一个用内存映射的方式来操作大文件,可以参考一下




using System.Runtime.InteropServices; 
  
 [DllImport("kernel32.dll")] 
 public static extern IntPtr CreateFileMapping(IntPtr hFile, 
     IntPtr lpFileMappingAttributes, uint flProtect, 
     uint dwMaximumSizeHigh, 
     uint dwMaximumSizeLow, string lpName); 
  
 [DllImport("kernel32.dll")] 
 public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint 
     dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, 
     IntPtr dwNumberOfBytesToMap); 
  
 [DllImport("kernel32.dll")] 
 public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); 
  
 [DllImport("kernel32.dll")] 
 public static extern bool CloseHandle(IntPtr hObject); 
  
 [DllImport("kernel32.dll")] 
 public static extern IntPtr CreateFile(string lpFileName,  
     int dwDesiredAccess, FileShare dwShareMode, IntPtr securityAttrs,  
     FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile); 
  
 [DllImport("kernel32.dll")] 
 public static extern uint GetFileSize(IntPtr hFile, IntPtr lpFileSizeHigh); 
  
 public const int GENERIC_READ = -2147483648; //0x80000000 
 public const int GENERIC_WRITE = 0x40000000; 
 public const int GENERIC_EXECUTE = 0x20000000; 
 public const int GENERIC_ALL = 0x10000000; 
 public const int FILE_ATTRIBUTE_NORMAL = 0x80; 
 public const int FILE_FLAG_SEQUENTIAL_SCAN = 0x8000000; 
 public const int INVALID_HANDLE_VALUE = -1; 
  
 public const int PAGE_NOACCESS = 1; 
 public const int PAGE_READONLY = 2; 
 public const int PAGE_READWRITE = 4; 
  
 public const int FILE_MAP_COPY = 1; 
 public const int FILE_MAP_WRITE = 2; 
 public const int FILE_MAP_READ = 4; 
  
  
 private void button1_Click(object sender, EventArgs e) 
 { 
     IntPtr vFileHandle = CreateFile(@"c:\temp\temp.txt", 
         GENERIC_READ | GENERIC_WRITE, FileShare.Read | FileShare.Write, 
         IntPtr.Zero,  FileMode.Open, 
         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, IntPtr.Zero); 
     if (INVALID_HANDLE_VALUE != (int)vFileHandle)  
     { 
         IntPtr vMappingHandle = CreateFileMapping( 
             vFileHandle, IntPtr.Zero, PAGE_READWRITE, 0, 0, "~MappingTemp"); 
         if (vMappingHandle != IntPtr.Zero) 
         { 
             IntPtr vHead = MapViewOfFile(vMappingHandle, 
                 FILE_MAP_COPY | FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, IntPtr.Zero); 
             if (vHead != IntPtr.Zero) 
             { 
                 uint vSize = GetFileSize(vFileHandle, IntPtr.Zero); 
                 for (int i = 0; i  <= vSize / 2; i++) 
                 { 
                     byte vTemp = Marshal.ReadByte((IntPtr)((int)vHead + i)); 
                     Marshal.WriteByte((IntPtr)((int)vHead + i), 
                         Marshal.ReadByte((IntPtr)((int)vHead + vSize - i - 1))); 
                     Marshal.WriteByte((IntPtr)((int)vHead + vSize - i - 1), vTemp); 
                 } 
                 UnmapViewOfFile(vHead); 
             } 
             CloseHandle(vMappingHandle); 
         } 
         CloseHandle(vFileHandle); 
     } 
 } 


 

#2


竟然有那么大的txt

#3


最好保存到新的文件中去。
除非你修改文件时不会影响后面的内容,也就是要修改的这一行比如占10个字节,修改后还要在此处填写10个字节

#4


1 楼太热情了

#5


最近有很多人喜欢提问 巨型文本文件搜索
为何放弃数据库用文本文档存数据?

#6


我记得用StreamReader,可以单个字符读取,也可以一性读取所有内容。所以针对你的问题,两种办法你可以根据效率自己选择一下,StreamReader读取返回是字符串string,应该不会有内在溢出的问题。文本文件中的制作转义符是\r\n。我觉得知道了这些信息做插入删除或修改都不难了,自己写一个处理类吧。

#7


顺带了 楼主818咋个去找系统的api函数嘛
以及功能调用