txt操作
C#解决读写包含汉字的txt文件时乱码的问题
C#解决读写包含汉字的txt文件时乱码的问题
当我们用System.IO.StreamReader读取包含汉字的txt文件时,经常会读出乱码(StreamWriater写文本文件也
有类似的问题),原因很简单,就是文件的编码(encoding)和StreamReader/Writer的encoding不对应。
为了解决这个问题,我写了一个类,来取得一个文本文件的encoding,这样我们就可以创建对应的
StreamReader和StreamWriter来读写,保证不会出现乱码现象。其实原理很简单,文本编辑器(比如XP自带的记事
本)在生成文本文件时,如果编码格式和系统默认的编码(中文系统下默认为GB2312)不一致时,会在txt文件开头
部分添加特定的“编码字节序标识(Encoding Bit Order Madk,简写为BOM)”,类似PE格式的"MZ"文件头。这样
它在读取时就可以根据这个BOM来确定该文本文件生成时所使用的Encoding。这个BOM我们用记事本等程序打开默认
是看不到的,但是用stream按字节读取时是可以读到的。我的这个TxtFileEncoding类就是根据这个BOM“文件头”
来确定txt文件生成时用到的编码的。
// 作者:袁晓辉
// 2005-8-8
// // // // // //
using System;
using System.Text;
using System.IO;
namespace Farproc.Text
{
/// <summary>
/// 用于取得一个文本文件的编码方式(Encoding)。
/// </summary>
public class TxtFileEncoding
{
public TxtFileEncoding()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/// <summary>
/// 取得一个文本文件的编码方式。如果无法在文件头部找到有效的前导符,Encoding.Default将被返回。
/// </summary>
/// <param name="fileName">文件名。</param>
/// <returns></returns>
public static Encoding GetEncoding(string fileName)
{
return GetEncoding(fileName, Encoding.Default);
}
/// <summary>
/// 取得一个文本文件流的编码方式。
/// </summary>
/// <param name="stream">文本文件流。</param>
/// <returns></returns>
public static Encoding GetEncoding(FileStream stream)
{
return GetEncoding(stream, Encoding.Default);
}
/// <summary>
/// 取得一个文本文件的编码方式。
/// </summary>
/// <param name="fileName">文件名。</param>
/// <param name="defaultEncoding">默认编码方式。当该方法无法从文件的头部取得有效的前导符时,将返回该编码方式。</param>
/// <returns></returns>
public static Encoding GetEncoding(string fileName, Encoding defaultEncoding)
{
FileStream fs = new FileStream(fileName, FileMode.Open);
Encoding targetEncoding = GetEncoding(fs, defaultEncoding);
fs.Close();
return targetEncoding;
}
/// <summary>
/// 取得一个文本文件流的编码方式。
/// </summary>
/// <param name="stream">文本文件流。</param>
/// <param name="defaultEncoding">默认编码方式。当该方法无法从文件的头部取得有效的前导符时,将返回该编码方式。</param>
/// <returns></returns>
public static Encoding GetEncoding(FileStream stream, Encoding defaultEncoding)
{
Encoding targetEncoding = defaultEncoding;
if(stream != null && stream.Length >= )
{
//保存文件流的前4个字节
byte byte1 = ;
byte byte2 = ;
byte byte3 = ;
byte byte4 = ;
//保存当前Seek位置
long origPos = stream.Seek(, SeekOrigin.Begin);
stream.Seek(, SeekOrigin.Begin); int nByte = stream.ReadByte();
byte1 = Convert.ToByte(nByte);
byte2 = Convert.ToByte(stream.ReadByte());
if(stream.Length >= )
{
byte3 = Convert.ToByte(stream.ReadByte());
}
if(stream.Length >= )
{
byte4 = Convert.ToByte(stream.ReadByte());
}
//根据文件流的前4个字节判断Encoding
//Unicode {0xFF, 0xFE};
//BE-Unicode {0xFE, 0xFF};
//UTF8 = {0xEF, 0xBB, 0xBF};
if(byte1 == 0xFE && byte2 == 0xFF)//UnicodeBe
{
targetEncoding = Encoding.BigEndianUnicode;
}
if(byte1 == 0xFF && byte2 == 0xFE && byte3 != 0xFF)//Unicode
{
targetEncoding = Encoding.Unicode;
}
if(byte1 == 0xEF && byte2 == 0xBB && byte3 == 0xBF)//UTF8
{
targetEncoding = Encoding.UTF8;
}
//恢复Seek位置
stream.Seek(origPos, SeekOrigin.Begin);
}
return targetEncoding;
}
}
}
由于在GB2312和UTF7编码都没有BOM,所以需要指定一个默认的Encoding,在找不到合法的BOM时,将返回这个
Encoding。有谁知道如何区分GB2312和UTF7编码txt文件的方法,也请告诉我。
由于只是static方法,所以不用new,直接通过类名调用方法,使用起来也很简单。
using System;
using Farproc.Text;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
string fileName = @"e:\a.txt";
//生成一个big endian Unicode编码格式的文本文件
StreamWriter sw = new StreamWriter(fileName, false, Encoding.BigEndianUnicode);//你可以试试其他编码,比如Encoding.GetEncoding("GB2312")或UTF8
sw.Write("这是一个String");
sw.Close();
//读取
Encoding fileEncoding = TxtFileEncoding.GetEncoding(fileName, Encoding.GetEncoding("GB2312"));//取得这txt文件的编码
Console.WriteLine("这个文本文件的编码为:" + fileEncoding.EncodingName);
StreamReader sr = new StreamReader(fileName, fileEncoding);//用该编码创建StreamReader
//用下面的方法虽然可以让系统自动判断文本文件的编码格式,但是我们无法取得该文本文件的编码
//sr.CurrentEncoding永远为 Unicode(UTF-8)
//StreamReader sr = new StreamReader(fileName, true);
//Console.WriteLine("这个文本文件的编码为:" + sr.CurrentEncoding.EncodingName);
Console.WriteLine("这个文本文件的内容为:" + sr.ReadToEnd());
sr.Close();
Console.ReadLine();
}
}
}
.NET下的string永远是Unicode的,所以只能判断txt文件的Encoding。对于byte[],只有自己知道它的
Encoding才能转换为string 转换为其他编码的byte[],一个例外是把整个txt文件通过stream读入byte[]后也可以根据它的前几个字节判断
Encoding,对于片断,我们就无能为力了:)
File的操作:下载到本地
File的操作:下载到本地 -- ::| 分类: java |字号 订阅
public boolean downLoad(String realFileURL,File file)
{
boolean Lflag = true;
try {
int bytesum=;
int byteread=; InputStream inStream=new FileInputStream(file);
FileOutputStream fs=new FileOutputStream(realFileURL);
byte[] buffer =new byte[]; while ((byteread=inStream.read(buffer))!=-)
{
bytesum+=byteread;
fs.write(buffer,,byteread);
}
inStream.close();
} catch (Exception e) {
System.out.println("下载结果(没有对说明文件做修改):"+e.getMessage());
// e.printStackTrace();
// TODO: handle exception
Lflag = false;
}
return Lflag;
}
c# 读 txt文件乱码,综合了一下,希望有用
c# 读 txt文件乱码,综合了一下,希望有用
-- :
第一篇
public class EncodingType
//编码问题目前为止,基本上没人解决,就连windows的IE的自动识别有时还识别错编码呢。
//如果文件有BOM则判断,如果没有就用系统默认编码,缺点:没有BOM的非系统编码文件会显示乱码。
//调用方法: EncodingType.GetType(filename)
{
public static System.Text.Encoding GetType(string FILE_NAME)
{
FileStream fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
System.Text.Encoding r = GetType(fs);
fs.Close();
return r;
}
public static System.Text.Encoding GetType(FileStream fs)
{
/*byte[] Unicode=new byte[]{0xFF,0xFE};
byte[] UnicodeBIG=new byte[]{0xFE,0xFF};
byte[] UTF8=new byte[]{0xEF,0xBB,0xBF};*/ BinaryReader r = new BinaryReader(fs, System.Text.Encoding.Default);
byte[] ss = r.ReadBytes();
r.Close();
//编码类型 Coding=编码类型.ASCII;
if (ss[] >= 0xEF)
{
if (ss[] == 0xEF && ss[] == 0xBB && ss[] == 0xBF)
{
return System.Text.Encoding.UTF8;
}
else if (ss[] == 0xFE && ss[] == 0xFF)
{
return System.Text.Encoding.BigEndianUnicode;
}
else if (ss[] == 0xFF && ss[] == 0xFE)
{
return System.Text.Encoding.Unicode;
}
else
{
return System.Text.Encoding.Default;
}
}
else
{
return System.Text.Encoding.Default;
}
}
}
第二篇 C# 读取txt 文件 乱码 解决方法
在c#中读取txt文件时,一至出现乱码,现找到解决方法如下: . using (StreamReader sr1 = new StreamReader(FILE_INFO_NAME,UnicodeEncoding.GetEncoding("GB2312")))
.StreamReader reader=new StreamReader(fileName,System.Text.Encoding.Default) 希望对大家有帮助。
下载文件,用filestream方法输出到浏览器时,在浏览器中能保存但是不能打开?
使用如下代码输出文件到客户端:
FileStream filestream = new FileStream( filepath,FileMode.Open,System.IO.FileAccess.Read, System.IO.FileShare.Read );
long filesize = filestream.Length; //让客户端浏览器正确识别这个文件的类型和文件大小
string filename = System.IO.Path.GetFileName( filepath ).ToLower();
HttpContext.Current.Response.ContentType = "text/plain " ;// fileType ;// "application/octet-stream ";
HttpContext.Current.Response.AddHeader( "Content-Disposition ", "attachment; filename=\ " " + HttpUtility.UrlEncode( filename,System.Text.Encoding.UTF8 ) + "\ "; ");
HttpContext.Current.Response.AddHeader( "Content-Length ",filesize.ToString()); //将文件中的数据发送到客户端
byte[] filebuffer = new byte[filesize];
filestream.Read(filebuffer,,(int)filesize);
HttpContext.Current.Response.BinaryWrite(filebuffer);
filestream.Close();
HttpContext.Current.Response.End();
点击下载时,客户端出现提示:您想打开或保存此文件吗?
点击[保存],正常;
但是点击[打开],会提示找不到文件[浏览器缓存地址],并问我要创建文件吗。 奇怪的是,同样的代码,在同样的服务器上,效果不同,我在asp.net创建了两个工程,
一个正常,另一个不正常。 恳请大家帮忙给解决一下,我无以回报,
以后我在论坛上遇到新手会多指导一下,作为对社会的回报吧
使用分页方式读取超大文件的性能试验
使用分页方式读取超大文件的性能试验
-- :: 我来说两句
收藏 我要投稿 [字体:小 大]
我们在编程过程中,经常会和计算机文件读取操作打交道。随着计算机功能和性能的发展,我们需要操作的文件尺寸也是越来越大。在.NET Framework中,我们一般使用FileStream来读取、写入文件流。当文件只有数十kB或者数MB时,一般的文件读取方式如Read()、ReadAll()等应用起来游刃有余,基本不会感觉到太大的延迟。但当文件越来越大,达到数百MB甚至数GB时,这种延迟将越来越明显,最终达到不能忍受的程度。
通常定义大小在2GB以上的文件为超大文件(当然,这个数值会随着科技的进步,越来越大)。对于这样规模的文件读取,普通方法已经完全不能胜任。这就要求我们使用更高效的方法,如内存映射法、分页读取法等。
内存映射(Memory Mapping)
内存映射的方法可以使用下面的Windows API实现。
LPVOID MapViewOfFile(HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
DWORD dwNumberOfBytesToMap);
虽然使用方便,但使用上限制较多,比如规定的分配粒度(Windows下通常为64KB)等。下面贴出内存映射法实例代码供参考,但本文不做进一步讨论。
内存映射法(使用MapViewOfFile) using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices; namespace BlueVision.SaYuan.FileMapping
{
public class ShareMemory
{
[DllImport( "user32.dll", CharSet = CharSet.Auto )]
public static extern IntPtr SendMessage( IntPtr hWnd, int Msg, int wParam, IntPtr lParam ); [DllImport( "Kernel32.dll", CharSet = CharSet.Auto )]
public static extern IntPtr CreateFileMapping( IntPtr hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName ); [DllImport( "Kernel32.dll", CharSet = CharSet.Auto )]
public static extern IntPtr OpenFileMapping( int dwDesiredAccess, [MarshalAs( UnmanagedType.Bool )] bool bInheritHandle, string lpName ); [DllImport( "Kernel32.dll", CharSet = CharSet.Auto )]
public static extern IntPtr MapViewOfFile( IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap ); [DllImport( "Kernel32.dll", CharSet = CharSet.Auto )]
public static extern bool UnmapViewOfFile( IntPtr pvBaseAddress ); [DllImport( "Kernel32.dll", CharSet = CharSet.Auto )]
public static extern bool CloseHandle( IntPtr handle ); [DllImport( "kernel32", EntryPoint = "GetLastError" )]
public static extern int GetLastError(); [DllImport( "kernel32.dll" )]
static extern void GetSystemInfo( out SYSTEM_INFO lpSystemInfo ); [StructLayout( LayoutKind.Sequential )]
public struct SYSTEM_INFO
{
public ushort processorArchitecture;
ushort reserved;
public uint pageSize;
public IntPtr minimumApplicationAddress;
public IntPtr maximumApplicationAddress;
public IntPtr activeProcessorMask;
public uint numberOfProcessors;
public uint processorType;
public uint allocationGranularity;
public ushort processorLevel;
public ushort processorRevision;
}
/// <summary>
/// 获取系统的分配粒度
/// </summary>
/// <returns></returns>
public static uint GetPartitionsize()
{
SYSTEM_INFO sysInfo;
GetSystemInfo( out sysInfo );
return sysInfo.allocationGranularity;
} const int ERROR_ALREADY_EXISTS = ; const int FILE_MAP_COPY = 0x0001;
const int FILE_MAP_WRITE = 0x0002;
const int FILE_MAP_READ = 0x0004;
const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004; const int PAGE_READONLY = 0x02;
const int PAGE_READWRITE = 0x04;
const int PAGE_WRITECOPY = 0x08;
const int PAGE_EXECUTE = 0x10;
const int PAGE_EXECUTE_READ = 0x20;
const int PAGE_EXECUTE_READWRITE = 0x40; const int SEC_COMMIT = 0x8000000;
const int SEC_IMAGE = 0x1000000;
const int SEC_NOCACHE = 0x10000000;
const int SEC_RESERVE = 0x4000000; IntPtr m_fHandle; IntPtr m_hSharedMemoryFile = IntPtr.Zero;
IntPtr m_pwData = IntPtr.Zero;
bool m_bAlreadyExist = false;
bool m_bInit = false;
uint m_MemSize = 0x1400000;//20M
long m_offsetBegin = ;
long m_FileSize = ;
FileReader File = new FileReader(); /// <summary>
/// 初始化文件
/// </summary>
/// <param name="MemSize">缓冲大小</param>
public ShareMemory( string filename, uint memSize )
{
// 分页映射文件时,每页的起始位置startpos,必须为64K的整数倍。
// memSize即缓存区的大小必须是系统分配粒度的整倍说,window系统的分配粒度是64KB
this.m_MemSize = memSize;
Init( filename );
} /// <summary>
/// 默认映射20M缓冲
/// </summary>
/// <param name="filename"></param>
public ShareMemory( string filename )
{
this.m_MemSize = 0x1400000;
Init( filename );
} ~ShareMemory()
{
Close();
} /// <summary>
/// 初始化共享内存
///
/// 共享内存名称
/// 共享内存大小
/// </summary>
/// <param name="strName"></param>
protected void Init( string strName )
{
//if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000; if ( !System.IO.File.Exists( strName ) ) throw new Exception( "未找到文件" ); System.IO.FileInfo f = new System.IO.FileInfo( strName ); m_FileSize = f.Length; m_fHandle = File.Open( strName ); if ( strName.Length > )
{
//创建文件映射
m_hSharedMemoryFile = CreateFileMapping( m_fHandle, IntPtr.Zero, ( uint )PAGE_READONLY, , ( uint )m_FileSize, "mdata" );
if ( m_hSharedMemoryFile == IntPtr.Zero )
{
m_bAlreadyExist = false;
m_bInit = false;
throw new Exception( "CreateFileMapping失败LastError=" + GetLastError().ToString() );
}
else
m_bInit = true; ////映射第一块文件
//m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_READ, 0, 0, (uint)m_MemSize);
//if (m_pwData == IntPtr.Zero)
//{
// m_bInit = false;
// throw new Exception("m_hSharedMemoryFile失败LastError=" + GetLastError().ToString());
//} }
}
/// <summary>
/// 获取高32位
/// </summary>
/// <param name="intValue"></param>
/// <returns></returns>
private static uint GetHighWord( UInt64 intValue )
{
return Convert.ToUInt32( intValue >> );
}
/// <summary>
/// 获取低32位
/// </summary>
/// <param name="intValue"></param>
/// <returns></returns>
private static uint GetLowWord( UInt64 intValue )
{ return Convert.ToUInt32( intValue & 0x00000000FFFFFFFF );
} /// <summary>
/// 获取下一个文件块 块大小为20M
/// </summary>
/// <returns>false 表示已经是最后一块文件</returns>
public uint GetNextblock()
{
if ( !this.m_bInit ) throw new Exception( "文件未初始化。" );
//if ( m_offsetBegin + m_MemSize >= m_FileSize ) return false; uint m_Size = GetMemberSize();
if ( m_Size == ) return m_Size; // 更改缓冲区大小
m_MemSize = m_Size; //卸载前一个文件
//bool l_result = UnmapViewOfFile( m_pwData );
//m_pwData = IntPtr.Zero; m_pwData = MapViewOfFile( m_hSharedMemoryFile, FILE_MAP_READ, GetHighWord( ( UInt64 )m_offsetBegin ), GetLowWord( ( UInt64 )m_offsetBegin ), m_Size );
if ( m_pwData == IntPtr.Zero )
{
m_bInit = false;
throw new Exception( "映射文件块失败" + GetLastError().ToString() );
}
m_offsetBegin = m_offsetBegin + m_Size; return m_Size; //创建成功
}
/// <summary>
/// 返回映射区大小
/// </summary>
/// <returns></returns>
private uint GetMemberSize()
{
if ( m_offsetBegin >= m_FileSize )
{
return ;
}
else if ( m_offsetBegin + m_MemSize >= m_FileSize )
{
long temp = m_FileSize - m_offsetBegin;
return ( uint )temp;
}
else
return m_MemSize;
} /// <summary>
/// 关闭内存映射
/// </summary>
public void Close()
{
if ( m_bInit )
{
UnmapViewOfFile( m_pwData );
CloseHandle( m_hSharedMemoryFile );
File.Close();
}
} /// <summary>
/// 从当前块中获取数据
/// </summary>
/// <param name="bytData">数据</param>
/// <param name="lngAddr">起始数据</param>
/// <param name="lngSize">数据长度,最大值=缓冲长度</param>
/// <param name="Unmap">读取完成是否卸载缓冲区</param>
/// <returns></returns>
public void Read( ref byte[] bytData, int lngAddr, int lngSize, bool Unmap )
{
if ( lngAddr + lngSize > m_MemSize )
throw new Exception( "Read操作超出数据区" );
if ( m_bInit )
{
// string bb = Marshal.PtrToStringAuto(m_pwData);//
Marshal.Copy( m_pwData, bytData, lngAddr, lngSize );
}
else
{
throw new Exception( "文件未初始化" );
} if ( Unmap )
{
bool l_result = UnmapViewOfFile( m_pwData );
if ( l_result )
m_pwData = IntPtr.Zero;
}
} /// <summary>
/// 从当前块中获取数据
/// </summary>
/// <param name="bytData">数据</param>
/// <param name="lngAddr">起始数据</param>
/// <param name="lngSize">数据长度,最大值=缓冲长度</param>
/// <exception cref="Exception: Read操作超出数据区"></exception>
/// <exception cref="Exception: 文件未初始化"></exception>
/// <returns></returns>
public void Read( ref byte[] bytData, int lngAddr, int lngSize )
{
if ( lngAddr + lngSize > m_MemSize )
throw new Exception( "Read操作超出数据区" );
if ( m_bInit )
{
Marshal.Copy( m_pwData, bytData, lngAddr, lngSize );
}
else
{
throw new Exception( "文件未初始化" );
}
} /// <summary>
/// 从当前块中获取数据
/// </summary>
/// <param name="lngAddr">缓存区偏移量</param>
/// <param name="byteData">数据数组</param>
/// <param name="StartIndex">数据数组开始复制的下标</param>
/// <param name="lngSize">数据长度,最大值=缓冲长度</param>
/// <exception cref="Exception: 起始数据超过缓冲区长度"></exception>
/// <exception cref="Exception: 文件未初始化"></exception>
/// <returns>返回实际读取值</returns>
public uint ReadBytes( int lngAddr, ref byte[] byteData, int StartIndex, uint intSize )
{
if ( lngAddr >= m_MemSize )
throw new Exception( "起始数据超过缓冲区长度" ); if ( lngAddr + intSize > m_MemSize )
intSize = m_MemSize - ( uint )lngAddr; if ( m_bInit )
{
IntPtr s = new IntPtr( ( long )m_pwData + lngAddr ); // 地址偏移
Marshal.Copy( s, byteData, StartIndex, ( int )intSize );
}
else
{
throw new Exception( "文件未初始化" );
} return intSize;
} /// <summary>
/// 写数据
/// </summary>
/// <param name="bytData">数据</param>
/// <param name="lngAddr">起始地址</param>
/// <param name="lngSize">个数</param>
/// <returns></returns>
private int Write( byte[] bytData, int lngAddr, int lngSize )
{
if ( lngAddr + lngSize > m_MemSize ) return ; //超出数据区
if ( m_bInit )
{
Marshal.Copy( bytData, lngAddr, m_pwData, lngSize );
}
else
{
return ; //共享内存未初始化
}
return ; //写成功 www.2cto.com
}
}
internal class FileReader
{
const uint GENERIC_READ = 0x80000000;
const uint OPEN_EXISTING = ;
System.IntPtr handle; [DllImport( "kernel32", SetLastError = true )]
public static extern System.IntPtr CreateFile(
string FileName, // file name
uint DesiredAccess, // access mode
uint ShareMode, // share mode
uint SecurityAttributes, // Security Attributes
uint CreationDisposition, // how to create
uint FlagsAndAttributes, // file attributes
int hTemplateFile // handle to template file
); [System.Runtime.InteropServices.DllImport( "kernel32", SetLastError = true )]
static extern bool CloseHandle
(
System.IntPtr hObject // handle to object
); public IntPtr Open( string FileName )
{
// open the existing file for reading
handle = CreateFile
(
FileName,
GENERIC_READ,
,
,
OPEN_EXISTING,
, ); if ( handle != System.IntPtr.Zero )
{
return handle;
}
else
{
throw new Exception( "打开文件失败" );
}
} public bool Close()
{
return CloseHandle( handle );
}
}
} 分页读取法(Paging)
另外一种高效读取文件的方法就是分页法,也叫分段法(Segmentation),对应的读取单位被称作页(Page)和段(Segment)。其基本思想是将整体数据分割至较小的粒度再进行处理,以便满足时间、空间和性能方面的要求。分页法的概念使用相当广泛,如嵌入式系统中的分块处理(Blocks)和网络数据的分包传输(Packages)。 在开始研究分页法前,先来看看在超大文件处理中,最为重要的问题:高速随机访问。桌面编程中,分页法通常应用于文字处理、阅读等软件,有时也应用在大型图片显示等方面。这类软件的一个特点就是数据的局部性,无论需要处理的文件有多么大,使用者的注意力(也可以称为视口ViewPort)通常只有非常局部的一点(如几页文档和屏幕大小的图片)。这就要求了接下来,我们要找到一种能够实现高速的随机访问,而这种访问效果还不能和文件大小有关(否则就失去了高速的意义)。事实上,以下我们研究的分页法就是利用了「化整为零」的方法,通过只读取和显示用户感兴趣的那部分数据,达到提升操作速度的目的。 参考上图,假设计算机上有某文件F,其内容为「」(引号「」中的内容,不含引号,下同),文件大小为FileLength=17字节,以PageSize=3对F进行分页,总页数PageCount=,得到页号为0~5的6个页面(图中页码=页号+)。各页面所含数据如下表所示。 页号 页码 内容 至头部偏移量 (Hex) 长度 0a 0b
0c 0d 0e
0f 可以看到,最后一页的长度为2(最后一页长度总是小于PageSize)。
当我们要读取「第n页」的数据(即页码=n)时,实际上读取的是页号PageNumber=n-1的内容。例如n=3时,PageNumber=,数据为「」,该页数据偏移量范围从0x06至0x08,长度为3(PageSize)。为便于讲述,在此约定:以下文字中,均只涉及页号,即PageNumber。
参考图2,设当PageNumber=x时,页x的数据范围为[offsetStart, offsetEnd],那么可以用如下的代码进行计算(C#2.0)。 offsetStart = pageNumber * pageSize; if(offsetStart + pageSize < fileSize)
{
offsetEnd = offsetStart + pageSize;
}
else
{
offsetEnd = fileSize - ;
} 我们常用的System.IO.FileStream类有两个重要的方法:Seek()和Read()。 // 将该流的当前位置设置为给定值。
public override long Seek (
long offset,
SeekOrigin origin
) // 从流中读取字节块并将该数据写入给定缓冲区中。
public override int Read (
[InAttribute] [OutAttribute] byte[] array,
int offset,
int count
) 利用这两个方法,我们可以指定每次读取的数据起始位置(offsetStart)和读取长度(offsetEnd - offsetStart),这样就可以读到任意指定的页数据。我们可以遍历读取所有页,这就相当于普通读取整个文件(实际操作中,一般不会有需求一次性读取上GB的文件)。
指定PageNumber,读取页数据 byte[] getPage(Int64 pageNumber)
{
if (fileStream == null || !fileStream.CanSeek || !fileStream.CanRead)
return null; if (pageNumber < || pageNumber >= pageCount)
return null; // absolute offileStreamet of read range
Int64 offsetStart = (Int64)pageNumber * (Int64)pageSize;
Int64 offsetEnd = ; if (pageNumber < pageCount - )
{
// not last pageNumber
offsetEnd = offsetStart + pageSize - ;
}
else
{
// last pageNumber
offsetEnd = fileSize - ;
} byte[] tmp = new byte[offsetEnd - offsetStart + ]; fileStream.Seek(offsetStart, SeekOrigin.Begin);
int rd = fileStream.Read(tmp, , (Int32)(offsetEnd - offsetStart + )); return tmp;
} 由于每次读取的数据长度(PageSize)远远小于文件长度(FileSize),所以使用分页法能够只读取程序需要的那部分数据,最大化提高程序的运行效率。下表是笔者在实验环境下对分页法读取文件的运行效率的测试。
CPU:Intel Core i3 380M @ .53GHz
内存:DDR3 2048MB x2
硬盘:TOSHIBA MK3265GSX ( GB) @ RPM
为尽量保证测试质量,测试前系统进行了重装、硬盘整理等维护操作。该硬盘性能测试结果如下图所示。 下面是为了测试分页法而制作的超大文件读取器界面截图,图中读取的是本次试验的用例之一Windows8消费者预览版光盘镜像(大小:.40GB)。 本次测试选择了「大、中、小」3种规格的测试文件作为测试用例,分别为: # 文件名 文件内容 大小(KB)
AlishaHead.png Poser Pro 6贴图 ,
ubuntu-11.10-desktop-i386.iso Ubuntu11.10桌面版镜像 ,
Windows8-ConsumerPreview-64bit-ChineseSimplified.iso Windows8消费者预览版64位简体中文版镜像 ,, 通过进行多次读取,采集到如下表A所示的文件读取数据结果。表中项目「分页(单页)」表示使用分页读取法,但设置页面大小为文件大小(即只有1页)进行读取。同样的,为了解分页读取的性能变化情况,使用普通读取方法(一次读取)采集到另一份数据结果,如下表B所示。 对用例#,该用例大小仅11MB,使用常规(单次)读取方法,仅用不到20ms即将全部内容读取完毕。而当采用分页法,随着分页大小越来越小,文件被划分为更多的页面,尽管随机访问文件内容使得文件操作更加方便,但在读取整个文件的时候,分页却带来了更多的消耗。例如当分页大小为1KB时,文件被分割为11,611个页面。读取整个文件时,需要重复调用11,611次FileStream.Read()方法,增加了很多消耗,如下图所示。(图中数据仅为全文读取操作对比) 从图中可以看到,当分页尺寸过分的小(1KB)时,这种过度追求微粒化反而导致了操作性能下降。可以看到,即实现了微粒化,能够进行随机访问,同时仍保有一定量的操作性能,分页大小为64KB和1MB是不错的选择。实际上,上文介绍的MapViewOfFile函数的推荐分页大小正是64KB。
对用例#,该用例大小为695.29MB,达到较大的尺寸,因此对读取缓存(cache)需求较高,同时也对合适的分页尺寸提出了要求。可以看到,和用例#1不同,当文件尺寸从11.34MB增加到近700MB时,分页尺寸随之相应的扩大,是提高操作性能的好方法(下图中1MB分页)。 对用例#,该用例达到3.4GB大小,符合我们对超大文件的定义。通过前述2个用例的分析,可以推测,为获得最佳性能,分页大小需继续提高(比如从1MB提高到4MB)。由于本次试验时间仓促,考虑不周,未使用「边读取、边丢弃」的测试算法,导致分页读取用例#3的数据时,数据不断在内存中积累,最终引发System.OutOfMemoryException异常,使得分页读取完整文件这项测试不能正常完成。这一问题,需在下次的试验当中加以解决和避免。 尽管如此,通过试验,仍然可以清楚的看到,在常规文件(GB以下级别)操作中,分页法具有高度灵活性,但额外开销大,全文读取速度慢的问题。当操作超大文件(GB以上级别)时,分页法的优势开始显现。极高的数据读取灵活性带来的是和文件大小无关的随机页面访问速度(仅和分页大小有关)。在这个级别上,文件大小往往远远超过常规方法所能读取的最大值(0x7FFFFFFF),因此只有使用分页法,积少成多,才能完成读取完整文件的工作。
分页法使用简单,思路清晰,具有很高的灵活性和与文件长度无关的随机读取能力,最大支持文件大小理论上能够达到8,, TB(Int64)。但同时它也具有额外开销大的特点,因此不适合小文件的操作。
通过扩展该方法,我们可以几乎在所有需要大量、重复、大范围算法处理的程序中加以应用分页法的「化整为零」思想,以减少计算粒度,实现计算的可持续进行。
分页法,以及上文提到的内存映射法,其实均早已出现多年,更是广泛应用于各个行业。笔者之所以仍旧撰写此文,一则锻炼自己的编程能力、语言归纳能力、文字写作能力,二则加深对方法的理解,通过试验得出的现象来深入方法的本质。鉴于笔者才疏学浅,在此妄言,有些词不达意,甚至出现谬误之处,还望各位读者多加批评、指正。 摘自 My name is Conmajia.
快速读取比较大的TXT文件
快速读取比较大的TXT文件
-- : 86人阅读 评论() 收藏 举报
刚开始想到是用文件映射,用C++做这个的比较多,后来找到CsvReader,发现速度还不错,使用也很简单! CsvReader可以快速读取比较大的TXT文件,当然CSV文件也是可以读取的,我测试过20M左右感觉不到卡,再大就没测过了 using System.IO;
using LumenWorks.Framework.IO.Csv; void ReadCsv()
{
// open the file "data.csv" which is a CSV file with headers
using (CsvReader csv =
new CsvReader(new StreamReader("data.csv"), true))
{
int fieldCount = csv.FieldCount;
string[] headers = csv.GetFieldHeaders(); while (csv.ReadNextRecord())
{
for (int i = ; i < fieldCount; i++)
Console.Write(string.Format("{0} = {1};",
headers[i], csv[i])); Console.WriteLine();
}
}
} 上面的true表示有CSV文件有标题行,如果是读取TXT,要把true改成false
读取txt文档并分页
jsp中代码
//在action中得到的nowpage
Stringnpage=String.valueOf(session.getAttribute("nowpage"));%>
<%
//读取的文件
Fileread=newFile("E:\\x.txt"); BufferedReaderbr=newBufferedReader(newInputStreamReader(newFileInputStream(read),"UTF-8"));
Stringtemp;
//行数
intj=;
//当前页
intnowpage;
//总页数
intpages=;
nowpage=Integer.parseInt(npage);
while((temp=br.readLine())!=null){
j++;
pages=j%==?j/:j/+;
if(j>(nowpage-)*&&j<=nowpage*){//根据当前页控制显示的行数
out.println(temp+"<br/>");
} }
br.close();
%>
<ahref="page.do?nowpage=1&mark=shou&method=gg">首页</a>
<%if(nowpage==){
}else{%>
<ahref="page.do?mark=shang&method=gg&nowpage=<%=nowpage%>">上一页</a>
<%}%>
<%if(nowpage>=pages){
}else{%>
<ahref="page.do?mark=xia&method=gg&nowpage=<%=nowpage%>">下一页</a>
<%}%>
<ahref="page.do?mark=mo&method=gg&nowpage=<%=pages%>">末页</a>
action中的代码: publicActionForwardgg(ActionMappingmapping,ActionFormform,
HttpServletRequestrequest,HttpServletResponseresponse)
throwsException{
Stringmark=request.getParameter("mark");
intnowpage=Integer.parseInt(request.getParameter("nowpage")); if(mark.equals("shou")){
nowpage=;
}
if(mark.equals("xia")){
nowpage++;
}
if(mark.equals("shang")){
nowpage--;
}
request.getSession().setAttribute("nowpage",nowpage);
Stringurl="/MyJsp.jsp";
returnnewActionForward(url);
}
读取Txt文件内容(按行读取
读取Txt文件内容(按行读取) -- ::| 分类: java |字号 订阅
//忻军
public static String readFileToString1(String filename){
StringBuffer str = new StringBuffer("");
String st = "";
try{
FileInputStream fs = new FileInputStream(filename);
InputStreamReader isr;
isr = new InputStreamReader(fs);
BufferedReader br = new BufferedReader(isr);
String data = "";
while((data = br.readLine())!=null){
str.append(data);
}
st = str.toString();
}catch(IOException es){
st = "";
}
return st;
}
超大文件的读取
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices; namespace ConsoleApplication51
{
class FileMap
{
[StructLayout(LayoutKind.Sequential)]
internal struct SYSTEM_INFO
{
public uint dwOemId;
public uint dwPageSize;
public uint lpMinimumApplicationAddress;
public uint lpMaximumApplicationAddress;
public uint dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public uint dwProcessorLevel;
public uint dwProcessorRevision;
} private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const int OPEN_EXISTING = ;
private const int INVALID_HANDLE_VALUE = -;
private const int FILE_ATTRIBUTE_NORMAL = 0x80;
private const uint FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000;
private const uint PAGE_READWRITE = 0x04; private const int FILE_MAP_COPY = ;
private const int FILE_MAP_WRITE = ;
private const int FILE_MAP_READ = ; /// <summary>
/// 内存映射文件句柄
/// </summary>
/// <param name="hFile"></param>
/// <param name="lpFileMappingAttributes"></param>
/// <param name="flProtect"></param>
/// <param name="dwMaximumSizeHigh"></param>
/// <param name="dwMaximumSizeLow"></param>
/// <param name="lpName"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
internal static extern IntPtr CreateFileMapping(IntPtr hFile,
IntPtr lpFileMappingAttributes, uint flProtect,
uint dwMaximumSizeHigh,
uint dwMaximumSizeLow, string lpName);
/// <summary>
/// 内存映射文件
/// </summary>
/// <param name="hFileMappingObject"></param>
/// <param name="dwDesiredAccess"></param>
/// <param name="dwFileOffsetHigh"></param>
/// <param name="dwFileOffsetLow"></param>
/// <param name="dwNumberOfBytesToMap"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
internal static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint
dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow,
uint dwNumberOfBytesToMap); /// <summary>
/// 撤消文件映像
/// </summary>
/// <param name="lpBaseAddress"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
internal static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); /// <summary>
/// 关闭内核对象句柄
/// </summary>
/// <param name="hObject"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
internal static extern bool CloseHandle(IntPtr hObject); /// <summary>
/// 打开要映射的文件
/// </summary>
/// <param name="lpFileName"></param>
/// <param name="dwDesiredAccess"></param>
/// <param name="dwShareMode"></param>
/// <param name="securityAttrs"></param>
/// <param name="dwCreationDisposition"></param>
/// <param name="dwFlagsAndAttributes"></param>
/// <param name="hTemplateFile"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
internal static extern IntPtr CreateFile(string lpFileName,
uint dwDesiredAccess, FileShare dwShareMode, IntPtr securityAttrs,
FileMode dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
/// <summary>
/// 得到文件大小
/// </summary>
/// <param name="hFile"></param>
/// <param name="highSize"></param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern uint GetFileSize(IntPtr hFile, out uint highSize); /// <summary>
/// 得到系统信息
/// </summary>
/// <param name="lpSystemInfo"></param>
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo); /// <summary>
/// 使用内存文件映射得到文件内容
/// </summary>
/// <param name="path">文件路径</param>
/// <returns></returns>
public StringBuilder GetFileContent(string path)
{
StringBuilder sb = new StringBuilder();
IntPtr fileHandle = CreateFile(path,
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)fileHandle)
{
IntPtr mappingFileHandle = CreateFileMapping(
fileHandle, IntPtr.Zero, PAGE_READWRITE, , , "~MappingTemp");
if (mappingFileHandle != IntPtr.Zero)
{
SYSTEM_INFO systemInfo = new SYSTEM_INFO(); ;
GetSystemInfo(ref systemInfo);
//得到系统页分配粒度
uint allocationGranularity = systemInfo.dwAllocationGranularity;
uint fileSizeHigh = ;
//get file size
uint fileSize = GetFileSize(fileHandle, out fileSizeHigh);
fileSize |= (((uint)fileSizeHigh) << );
//关闭文件句柄
CloseHandle(fileHandle);
uint fileOffset = ;
uint blockBytes = * allocationGranularity;
if (fileSize < * allocationGranularity)
blockBytes = fileSize;
//分块读取内存,适用于几G的文件
while (fileSize > )
{
// 映射视图,得到地址
IntPtr lpbMapAddress = MapViewOfFile(mappingFileHandle, FILE_MAP_COPY | FILE_MAP_READ | FILE_MAP_WRITE,
(uint)(fileOffset >> ), (uint)(fileOffset & 0xFFFFFFFF),
blockBytes);
if (lpbMapAddress == IntPtr.Zero)
{
return sb;
}
// 对映射的视图进行访问
byte[] temp = new byte[blockBytes];
//从非托管的内存中复制内容到托管的内存中
Marshal.Copy(lpbMapAddress, temp, , (int)blockBytes); //用循环太慢了,文件有几M的时候就慢的要死,还是用上面的方法直接
//for (uint i = 0; i < dwBlockBytes; i++)
//{
// byte vTemp = Marshal.ReadByte((IntPtr)((int)lpbMapAddress + i));
// temp[i] = vTemp;
//} //此时用ASCII解码比较快,但有中文会有乱码,用gb2312即ANSI编码也比较快,16M的文件大概4秒就读出来了
//但用unicode解码,文件大的时候会非常慢,会现卡死的状态,不知道为什么?
//ASCIIEncoding encoding = new ASCIIEncoding();
//System.Text.UnicodeEncoding encoding = new UnicodeEncoding();
//sb.Append(encoding.GetString(temp));
sb.Append(System.Text.Encoding.GetEncoding("gb2312").GetString(temp));
// 撤消文件映像
UnmapViewOfFile(lpbMapAddress);
// 修正参数
fileOffset += blockBytes;
fileSize -= blockBytes;
} //close file mapping handle
CloseHandle(mappingFileHandle);
}
}
return sb;
} }
}
按行读取
TXT格式如下:
aaa,
bbb,
ccc,
... 如何把TXT改成写
aaa,
bbb,
ccc,
.....
求助
我来帮他解答
-- : 满意回答
List<string> result = new List<string>();
String[] arr = System.IO.File.ReadAllLines("file_path");
string temp;
foreach(string item in arr)
{
string[] tmpArr = item.Split(new char[]{','});
tmpArr[]=你的处理 result.Add(tmpArr[]+","+tmpArr[]);
} System.IO.File.WriteAllLines("file_path",result.toArray(),Encoding.Default); 大概的思路,参考下
using System;
using System.IO; class TextRW
{
static void Main()
{
TextWriter stringWriter = new StringWriter();
using(TextWriter streamWriter = new StreamWriter("InvalidPathChars.txt"))
{
WriteText(stringWriter);
WriteText(streamWriter);
} TextReader stringReader = new StringReader(stringWriter.ToString());
using(TextReader streamReader = new StreamReader("InvalidPathChars.txt"))
{
ReadText(stringReader);
ReadText(streamReader);
}
} static void WriteText(TextWriter textWriter)
{
textWriter.Write("Invalid file path characters are: ");
textWriter.Write(Path.InvalidPathChars);
textWriter.Write('.');
} static void ReadText(TextReader textReader)
{
Console.WriteLine("From {0} - {1}",
textReader.GetType().Name, textReader.ReadToEnd());
}
}
txt操作的更多相关文章
- php 的txt操作,加入类容
<?php $fr=fopen("./data/test.txt",'a'); //fopen(位置,打开方式) if(!$fr) { echo " error&q ...
- python之数据驱动Txt操作
一.新建数据Mail163.txt文本 二.Txt_Mail163.py脚本如下: import unittestfrom selenium import webdriverfrom selenium ...
- 用 JSP 实现对文件的相关操作
前段时间一直忙着作业,实验,动手的时间真是少之又少,今天终于可以继续和大家分享关于 JSP 的学习心得. 简单总结一下吧: JSP 理论性很强,感觉就是纯语法. 我更偏向于实际编写代码,这样更容易理解 ...
- 微信硬件平台(九) 自己的服务器从微信获取token并保存txt
1安装crontab: yum install crontabs 说明: service crond start //启动服务 service crond stop //关闭服务 service cr ...
- 笔记:javascript操作iframe内的DOM元素,及调用iframe内的方法
iframe相当于一个嵌入在网页内的浏览器,它与当前网页是隔离的. 但有时我们也需要在当前网页操作iframe内的元素或操作iframe内的javascript方法. 在网页内操作DOM元素,是使用d ...
- linux基础的基础命令操作
一.开启Linux操作系统,要求以root用户登录GNOME图形界面,语言支持选择为汉语 操作:su - root 二.使用快捷键切换到虚拟终端2,使用普通用户身份登录,查看系统提示符 操作:ctrl ...
- hadoop之hive高级操作
在输出结果较多,需要输出到文件中时,可以在hive CLI之外执行hive -e "sql" > output.txt操作 但当SQL语句太长或太多时,这种方式不是很方便,可 ...
- [Python基础]006.IO操作
IO操作 输入输出 print raw_input input 文件 打开文件 关闭文件 读文件 写文件 文件指针 实例 输入输出 输入输出方法都是Python的内建函数,并且不需要导入任何的包就可以 ...
- 魅族mx4 pro连电脑,adb无法获取devices信息解决
根据 flyme 的文档: K:\MX4 USB Reference Manual\简体\MX4_ADB_参考说明书.txt 操作如下: 二.Windows XP中文环境1. 建立或修改C:\Doc ...
随机推荐
- mybatis缓存机制(转)
缓存在互联网系统中是非常重要的, 其主要作用是将数据保存到内存中, 当用户查询数据 时, 优先从缓存容器中获取数据,而不是频繁地从数据库中查询数据,从而提高查询性能.目 前流行的缓存服务器有Mongo ...
- Jenkins+Git+Gitlab+Ansible实现持续集成自动化部署静态网站
环境准备 三台主机: 一台主机部署jenkins和作为ansible的管理主机 一台主机部署gitlab和ansible的节点1 一台主机为ansible的节点2 防火墙和apache服务关闭 第一步 ...
- Node.js实战6:定时器,使用timer延迟执行。
setTimeout 在nodejs中,通过setTimeout函数可以达到延迟执行的效果,这个函数也常被称为定时器. 一个简单的例子: console.log( (new Date()).getSe ...
- Maven安装、配置环境变量
一.首先在官网下载安装maven 1.进入官网 2.找到下载位置 3.点进去后是最新版的,若需要最新版就下这个,需要旧版本接着往下滑 4.下载历史版本 (1)点击"archives" ...
- Python入门习题7.分别统计输入各类字符个数
例7.用户从键盘输入一行字符,编写一个程序,统计并输出其中的英文字符(包括中文字符).数字.空格和其他字符个数. #字符数统计.py Str = input('请输入一行字符:') alpha = 0 ...
- Spring Cloud Stream 进行服务之间的通讯
Spring Cloud Stream Srping cloud Bus的底层实现就是Spring Cloud Stream,Spring Cloud Stream的目的是用于构建基于消息驱动(或事件 ...
- python学习第七天流程控制循环while和循环for区别
流程控制循环是任何编程语言都有一种循环结构,在python while 和break continue 搭配使用,还一种while ....else ......,for循环有序列表和字符串 whil ...
- Java-技术专区-设计模式-reactor模式
模型: 反应器模式做法是:汽车是乘客访问的主体(Reactor),乘客上车后,到售票员(acceptor)处登记,之后乘客便可以休息睡觉去了,当到达乘客所要到达的目的地后,售票员将其唤 ...
- SQL 日期格式化与格式转化
日期格式化 Select CONVERT(varchar(), GETDATE(), ): :57AM Select CONVERT(varchar(), GETDATE(), ): // Selec ...
- NGUI的Lebal需注意问题
1,为什么调节字体大小时,字体大小没变化,我们需要调节两个地方,如下图框柱显示 调节font size和size才可以同时控制字体的大小 2,label有时是不支持输入中文,但是支持复制进去,则这时我 ...