对于想了解c#–FileStream.ReadByte:字节永远不是负数?的读者,本文将是一篇不可错过的文章,我们将详细介绍c#中以字节为单位进行文件读写的类是,并且为您提供关于.NETFileStr
对于想了解c# – FileStream.ReadByte:字节永远不是负数?的读者,本文将是一篇不可错过的文章,我们将详细介绍c#中以字节为单位进行文件读写的类是,并且为您提供关于.NET FileStream文件流,StreamReader文本流,MemoryStream内存流几种流的实例、2019.04.19 读书笔记 比较File.OpenRead()和File.ReadAllBytes()的差异、ASP.NET Core – Byte, Stream, File 基础、C# .net core StreamReader读文件流改为FileStream的有价值信息。
本文目录一览:- c# – FileStream.ReadByte:字节永远不是负数?(c#中以字节为单位进行文件读写的类是)
- .NET FileStream文件流,StreamReader文本流,MemoryStream内存流几种流的实例
- 2019.04.19 读书笔记 比较File.OpenRead()和File.ReadAllBytes()的差异
- ASP.NET Core – Byte, Stream, File 基础
- C# .net core StreamReader读文件流改为FileStream
c# – FileStream.ReadByte:字节永远不是负数?(c#中以字节为单位进行文件读写的类是)
FileSystem.ReadByte
The byte,cast to an Int32,or -1 if the end of the stream has been reached.
所以-1基本上是一个“神奇的价值”.这是否意味着从流返回的字节永远不会是负数?如果没有,为什么不呢?
解决方法
sbyte数据类型是有符号字节,因此它的值介于-128和127之间.
(在某些其他语言中,例如Java,字节数据类型已签名.)
.NET FileStream文件流,StreamReader文本流,MemoryStream内存流几种流的实例
一、FileStream文件流
1.读取数据
1 public class ReadFile
2 {
3 /// <summary>
4 /// 读取文件
5 /// FileMode.Create 创建一个新文件,如果文件已经存在则改写旧文件
6 /// FileMode.CreateNew 创建一个文件,如果文件存在会发生异常,提示文件已经存在
7 /// FileMode.Open 打开文件,如果文件不存在则异常
8 /// FileMode.OpenOrCreate 打开文件,如果文件不存在,则创建一个新的文件并且打开文件
9 /// FileMode.Append 打开现有文件,并且在现有文件内容后面追加,如果文件不存在则异常
10 /// FileMode.Truncate 根据现有操作系统,截取文件里面的内容,如果文件不存在则异常
11 /// </summary>
12 public static void Read(string FilePath)
13 {
14 FileStream fileStream = null;
15 try
16 {
17 fileStream = new FileStream(FilePath, FileMode.Truncate);
18 byte[] bytes = new byte[fileStream.Length];
19 int read = fileStream.Read(bytes, 0, bytes.Length);
20 var result = Encoding.UTF8.GetString(bytes);
21 }
22 catch (Exception e)
23 {
24 if (fileStream != null)
25 {
26 fileStream.Dispose();
27 }
28 Console.WriteLine(e.Message);
29 }
30 finally
31 {
32 if (fileStream != null)
33 {
34 fileStream.Close();
35 fileStream.Dispose();
36 }
37 }
38 }
39 }
2.写入数据
1 public class WriteFile
2 {
3 public static void WriteText(string FilePath,string writeString)
4 {
5 FileStream fileStream = null;
6 try
7 {
8 //根据路径打开文件
9 fileStream = new FileStream(@"C:\Users\Administrator\source\repos\OperatFile\OperatFile\1.txt", FileMode.Append);
10 //把字符串转化成字节
11 byte[] bytes = Encoding.UTF8.GetBytes(writeString);
12 //写入到文件
13 fileStream.Write(bytes, 0, bytes.Length);
14 }
15 catch (Exception e)
16 {
17 if (fileStream != null)
18 {
19 fileStream.Dispose();
20 }
21 Console.WriteLine(e.Message);
22 }
23 finally
24 {
25 //关闭和释放
26 if (fileStream != null)
27 {
28 fileStream.Close();
29 fileStream.Dispose();
30 }
31 }
32 }
33 }
二、StreamReader文本流
1.读取数据
1 public class SteamReadFile
2 {
3 /// <summary>
4 /// 读取文件
5 /// </summary>
6 /// <param name="filePath">文件路径</param>
7 public static void ReadFile(string FilePath)
8 {
9 try
10 {
11 using (StreamReader sr = new StreamReader(FilePath))
12 {
13 var result = sr.ReadToEnd();
14 Console.WriteLine(result);
15 }
16 }
17 catch (Exception e)
18 {
19
20 throw new Exception(e.Message);
21 }
22 }
23 }
2.写入数据
1 public class StreamWriteFile
2 {
3 /// <summary>
4 /// 写入文件
5 /// </summary>
6 /// <param name="FilePath">文件路径</param>
7 /// <param name="WriteString">待写入字符串</param>
8 public static void WriteFile(string FilePath,string WriteString)
9 {
10 try
11 {
12 using (StreamWriter sr = new StreamWriter(FilePath))
13 {
14 sr.WriteLine(WriteString);
15 }
16 }
17 catch (Exception e)
18 {
19 throw new Exception(e.Message);
20 }
21 }
22 }
3.写入日志实例
1 public class LogHelper
2 {
3 /// <summary>
4 /// 文件路径
5 /// </summary>
6 public static string FilePath = @"C:\Users\Administrator\source\repos\OperatFile\OperatFile\Files";
7 static LogHelper()
8 {
9 //判断文件夹是否存在,如果不存在,则重新创建
10 if (!Directory.Exists(FilePath))
11 {
12 Directory.CreateDirectory(FilePath);
13 }
14 }
15 /// <summary>
16 /// 日志写入
17 /// Path.Combine(str1,str2,str3) 把传入的参数拼接起来,然后返回新的字符串
18 /// File.AppendText(fullPath) 根据文件路径,把新写入的内容,拼接到文本后面
19 /// </summary>
20 public static void WriteLog()
21 {
22 try
23 {
24 var sb = BindData();
25 string fullPath = Path.Combine(FilePath, $"{DateTime.Now.ToString("yyyy-MM-dd")}.txt");
26 //判断文件是否存在,如果不存在,则新建文件
27 if (!File.Exists(fullPath))
28 {
29 File.Create(fullPath);
30 }
31 using (StreamWriter sw = File.AppendText(fullPath))
32 {
33 sw.WriteLine(sb.ToString());
34 }
35 }
36 catch (Exception e)
37 {
38 throw new Exception(e.Message);
39 }
40
41 }
42 /// <summary>
43 /// 绑定日志信息
44 /// </summary>
45 /// <returns></returns>
46 private static StringBuilder BindData()
47 {
48 StringBuilder sb = new StringBuilder();
49 DateTime operatDateTime = DateTime.Now;
50 string content = "读写文件功能";
51 string operators = "小明";
52 sb.AppendLine($"操作时间:{operatDateTime}");
53 sb.AppendLine($"操作内容:{content}");
54 sb.AppendLine($"操作人:{operators}");
55 sb.AppendLine("------------------------------------------------------------------------------------------");
56 return sb;
57 }
58 }
三、MemoryStream内存流
1 /// <summary>
2 /// 根据URL读取内容到内存流
3 /// </summary>
4 /// <param name="url"></param>
5 /// <returns></returns>
6 public static string DownLoadByUrl(string url)
7 {
8 string result = string.Empty;
9 MemoryStream ms = null;
10 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
11 HttpWebResponse response = request.GetResponse() as HttpWebResponse;
12 using (var stream = response.GetResponseStream())
13 {
14 byte[] buffer = new byte[response.ContentLength];
15 int actuallyRead = 0, offset = 0;
16 do
17 {
18 actuallyRead = stream.Read(buffer, offset, buffer.Length - offset);
19 offset += actuallyRead;
20
21 } while (actuallyRead > 0);
22 ms = new MemoryStream(buffer);
23 ms.Seek(0, SeekOrigin.Begin);
24 var byteArray = new byte[ms.Length];
25 ms.Read(byteArray, 0, byteArray.Length);
26 result = Encoding.UTF8.GetString(byteArray);
27 }
28 response.Close();
29 response.Dispose();
30 return result;
31 }
2019.04.19 读书笔记 比较File.OpenRead()和File.ReadAllBytes()的差异
最近涉及到流的获取与转化,终于要还流的债了。
百度了一下,看到这样的两条回复,于是好奇心,决定看看两种写法的源码差异。
先来看看OpenRead()
public static FileStream OpenRead(string path) =>
new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
//构造函数又调用了其他构造函数,继续深入
[SecuritySafeCritical]
public FileStream(string path, FileMode mode, FileAccess access, FileShare share) : this(path, mode, access, share, 0x1000, FileOptions.None, Path.GetFileName(path), false)
{
}
//调用了Init 初始化
[SecurityCritical]
internal FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, string msgPath, bool bFromProxy)
{
Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share);
this.Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, false, false);
}
//读取数据到流中,过程就没什么可以看的了
[SecuritySafeCritical]
private unsafe void Init(string path, FileMode mode, FileAccess access, int rights, bool useRights, FileShare share, int bufferSize, FileOptions options, Win32Native.SECURITY_ATTRIBUTES secAttrs, string msgPath, bool bFromProxy, bool useLongPath, bool checkHost)
{
int num;
if (path == null)
{
throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path"));
}
if (path.Length == 0)
{
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
}
FileSystemRights rights2 = (FileSystemRights) rights;
this._fileName = msgPath;
this._exposedHandle = false;
FileShare share2 = share & ~FileShare.Inheritable;
string paramName = null;
if ((mode < FileMode.CreateNew) || (mode > FileMode.Append))
{
paramName = "mode";
}
else if (!useRights && ((access < FileAccess.Read) || (access > FileAccess.ReadWrite)))
{
paramName = "access";
}
else if (useRights && ((rights2 < FileSystemRights.ListDirectory) || (rights2 > FileSystemRights.FullControl)))
{
paramName = "rights";
}
else if ((share2 < FileShare.None) || (share2 > (FileShare.Delete | FileShare.ReadWrite)))
{
paramName = "share";
}
if (paramName != null)
{
throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Enum"));
}
if ((options != FileOptions.None) && ((options & 0x3ffbfff) != FileOptions.None))
{
throw new ArgumentOutOfRangeException("options", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
}
if (bufferSize <= 0)
{
throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
}
if (((!useRights && ((access & FileAccess.Write) == 0)) || (useRights && ((rights2 & FileSystemRights.Write) == 0))) && (((mode == FileMode.Truncate) || (mode == FileMode.CreateNew)) || ((mode == FileMode.Create) || (mode == FileMode.Append))))
{
if (!useRights)
{
object[] objArray1 = new object[] { mode, access };
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&AccessCombo", objArray1));
}
object[] values = new object[] { mode, rights2 };
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&RightsCombo", values));
}
if (useRights && (mode == FileMode.Truncate))
{
if (rights2 != FileSystemRights.Write)
{
object[] objArray3 = new object[] { mode, rights2 };
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileModeTruncate&RightsCombo", objArray3));
}
useRights = false;
access = FileAccess.Write;
}
if (!useRights)
{
num = (access == FileAccess.Read) ? -2147483648 : ((access == FileAccess.Write) ? 0x40000000 : -1073741824);
}
else
{
num = rights;
}
int maxPathLength = useLongPath ? 0x7fff : (AppContextSwitches.BlockLongPaths ? 260 : 0x7fff);
string fullPath = Path.NormalizePath(path, true, maxPathLength);
this._fileName = fullPath;
if ((!CodeAccessSecurityEngine.QuickCheckForAllDemands() || AppContextSwitches.UseLegacyPathHandling) && fullPath.StartsWith(@"\\.\", StringComparison.Ordinal))
{
throw new ArgumentException(Environment.GetResourceString("Arg_DevicesNotSupported"));
}
bool flag = false;
if ((!useRights && ((access & FileAccess.Read) != 0)) || (useRights && ((rights2 & FileSystemRights.ReadAndExecute) != 0)))
{
if (mode == FileMode.Append)
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidAppendMode"));
}
flag = true;
}
if (CodeAccessSecurityEngine.QuickCheckForAllDemands())
{
FileIOPermission.EmulateFileIOPermissionChecks(fullPath);
}
else
{
FileIOPermissionAccess noAccess = FileIOPermissionAccess.NoAccess;
if (flag)
{
noAccess |= FileIOPermissionAccess.Read;
}
if (((!useRights && ((access & FileAccess.Write) != 0)) || (useRights && ((rights2 & (FileSystemRights.TakeOwnership | FileSystemRights.ChangePermissions | FileSystemRights.Delete | FileSystemRights.Write | FileSystemRights.DeleteSubdirectoriesAndFiles)) != 0))) || ((useRights && ((rights2 & FileSystemRights.Synchronize) != 0)) && (mode == FileMode.OpenOrCreate)))
{
if (mode == FileMode.Append)
{
noAccess |= FileIOPermissionAccess.Append;
}
else
{
noAccess |= FileIOPermissionAccess.Write;
}
}
AccessControlActions control = ((secAttrs != null) && (secAttrs.pSecurityDescriptor != null)) ? AccessControlActions.Change : AccessControlActions.None;
string[] fullPathList = new string[] { fullPath };
FileIOPermission.QuickDemand(noAccess, control, fullPathList, false, false);
}
share &= ~FileShare.Inheritable;
bool flag2 = mode == FileMode.Append;
if (mode == FileMode.Append)
{
mode = FileMode.OpenOrCreate;
}
if ((options & FileOptions.Asynchronous) != FileOptions.None)
{
this._isAsync = true;
}
else
{
options &= ~FileOptions.Asynchronous;
}
int dwFlagsAndAttributes = (int) options;
dwFlagsAndAttributes |= 0x100000;
int newMode = Win32Native.SetErrorMode(1);
try
{
string str3 = fullPath;
if (useLongPath)
{
str3 = Path.AddLongPathPrefix(str3);
}
this._handle = Win32Native.SafeCreateFile(str3, num, share, secAttrs, mode, dwFlagsAndAttributes, IntPtr.Zero);
if (this._handle.IsInvalid)
{
int errorCode = Marshal.GetLastWin32Error();
if ((errorCode == 3) && fullPath.Equals(Directory.InternalGetDirectoryRoot(fullPath)))
{
errorCode = 5;
}
bool flag4 = false;
if (!bFromProxy)
{
try
{
FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, this._fileName, false, false);
flag4 = true;
}
catch (SecurityException)
{
}
}
if (flag4)
{
__Error.WinIOError(errorCode, this._fileName);
}
else
{
__Error.WinIOError(errorCode, msgPath);
}
}
}
finally
{
Win32Native.SetErrorMode(newMode);
}
if (Win32Native.GetFileType(this._handle) != 1)
{
this._handle.Close();
throw new NotSupportedException(Environment.GetResourceString("NotSupported_FileStreamOnNonFiles"));
}
if (this._isAsync)
{
bool flag5 = false;
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
try
{
flag5 = ThreadPool.BindHandle(this._handle);
}
finally
{
CodeAccessPermission.RevertAssert();
if (!flag5)
{
this._handle.Close();
}
}
if (!flag5)
{
throw new IOException(Environment.GetResourceString("IO.IO_BindHandleFailed"));
}
}
if (!useRights)
{
this._canRead = (access & FileAccess.Read) > 0;
this._canWrite = (access & FileAccess.Write) > 0;
}
else
{
this._canRead = (rights2 & FileSystemRights.ListDirectory) > 0;
this._canWrite = ((rights2 & FileSystemRights.CreateFiles) != 0) || ((rights2 & FileSystemRights.AppendData) > 0);
}
this._canSeek = true;
this._isPipe = false;
this._pos = 0L;
this._bufferSize = bufferSize;
this._readPos = 0;
this._readLen = 0;
this._writePos = 0;
if (flag2)
{
this._appendStart = this.SeekCore(0L, SeekOrigin.End);
}
else
{
this._appendStart = -1L;
}
}
从上面的源码可以看出,OpenRead会把无论多大的文件都读取到FileStream中,能有多大呢?FileStream.Length可是long型的,就是2的63次方了,2的40次方是1T,大约就是8MT吧,我们的常用硬盘是没这么大的了,可以说能读出天荒地老了。那么图片中的第一中写法,读取没错,但是转换int就留下了隐患,int的最大限制是2G,如果文件超过2G,那么转换就会被截取,导致读到data里的数据就不完整了。所以一定不要偷懒,由于FileStream.Read的参数是int型的,一定要判断流的长度,如果超过了int最大值,要循环read。
再来看看File.ReadAllBytes(),上源码:
[SecurityCritical]
private static byte[] InternalReadAllBytes(string path, bool checkHost)
{
byte[] buffer;
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x1000, FileOptions.None, Path.GetFileName(path), false, false, checkHost))//这里也是和OpenRead一样,把文件全部读取进来了
{
int offset = 0;
long length = stream.Length;
if (length > 0x7fffffffL)//这里才是关键,对长度做了一个判断,如果超过了2G,就抛异常了,所以决定了这个方法的文件不能超过2G
{
throw new IOException(Environment.GetResourceString("IO.IO_FileTooLong2GB"));
}
int count = (int) length;
buffer = new byte[count];
while (count > 0)
{
int num4 = stream.Read(buffer, offset, count);
if (num4 == 0)
{
__Error.EndOfFile();
}
offset += num4;
count -= num4;
}
}
return buffer;
}
第二种写法会导致在读取文件超过2G后抛出异常,所以使用时要确定文件的大小,否则就用OpenRead()。
所以图中两种写法都可能存在隐患的BUG。
当然,在确定了不可能超过2G的情况下,还是可以自由使用的。
ASP.NET Core – Byte, Stream, File 基础
前言
以前的文章: Stream 基础和常用 和 IO 常用.
这篇主要是做一个整理, 方便要用的时候 warm up.
基本术语和概念
先过一边基本术语和概念:
Bits
Bits 就是比特. 它是最小的单位, 1 bit = 1 个二进制, 0 或者 1.
通信的时候就是通过电压高低, 来表示 0 或 1. 在由二进制来表达万物 (就好比摩斯密码一样啦)
Bytes
Bytes 是字节. 1 byte = 8 bits. 它也是一个单位.
Stream
Stream 是流的概念. 如果 bytes 是鱼, 那么 stream 就是河流. 通信的时候就好像建立了河流. 然后上面有很多鱼游来游去.
Bytes encode
通信用的是二进制, 那自然是需要 encode 咯, 比如把 0 和 1 变成 alphabet (英文字母).
1 个 alphabet 需要 1 byte 来表示, 而汉字需要 2 bytes 来表示 (也要 依据 encode 手法, 但大概可以这样去理解).
还有很多种 encode 的方式, 比如: ASCII, Unicode, UTF, Base64
char, char[], string
char 是 C# 中用来装字母的, 1 char = 2 bytes, 所以它也可以撞汉字.
char[] 就是很多字母咯.
string 是 char[] 的封装. 它包含了对 char[] 的操作, 比如 char[] 的 length 是不可以变的, 但 string 可以.
ASP.NET Core Stream 结构
ASP.NET Core build-in 了许多 Class 来处理 Bytes, Stream 这些冬冬.
Stream(抽象类) > TextReader(抽象类) > StreamReader(实体类) > MemoryStream(实体类), FileStream(实体类) 等等
顾名思义, MemoryStream 是负责缓存的, FileStream 是文件的.
串起来理解 & 运用场景
万物都是二进制
在数码世界里, 万物都是二进制 (bits) 0 或 1 来表示的, 1 个文件它储存在磁盘里就是二进制, 2 台电脑通信传输的依然是二进制.
这个是最底层的逻辑.
二进制如果表达万物?
0 和 1 对电脑来说 ok, 对人来说可不行, 所以需要转换. 二进制转换成英文字母, 汉字是有规范的, 这就是所谓的 ASCII, Unicode, UTF, 等等.
运用场景
假设, 系统的需求是让用户输入一段字母, 然后生成 1 个 word.txt 文件.
当获取到 user input (string), 先把它转换成 bytes. 然后创建文件, 并把 bytes 写进去.
在开发种我们需要掌握好, encode (清楚如何 decode/encode bytes), file type (文件的类型), 读写 stream 的 bytes.
C# .net core StreamReader读文件流改为FileStream
见Stackoverflow的提问.
原先在NET Framework下,StreamReader中提供重载的方式直接读取文件流.但是在.net core中已经取消了该重载方法,为了移植到.net core只需添加一行代码即可.
string fileName = "xxxx";
...
//原来只用这一句
//StreamReader mysr = new StreamReader(fileName, Encoding.UTF8);
//现在需要添加FileStream.
var sw = new FileStream(fileName, FileMode.Open);
StreamReader mysr = new StreamReader(sw);
...
关于c# – FileStream.ReadByte:字节永远不是负数?和c#中以字节为单位进行文件读写的类是的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于.NET FileStream文件流,StreamReader文本流,MemoryStream内存流几种流的实例、2019.04.19 读书笔记 比较File.OpenRead()和File.ReadAllBytes()的差异、ASP.NET Core – Byte, Stream, File 基础、C# .net core StreamReader读文件流改为FileStream等相关知识的信息别忘了在本站进行查找喔。
本文标签: