[英]Is there any faster alternative to FileStream.WriteByte() method or any way to speed up the FileStream.WriteByte() in C#?
我是C#編程的初學者。 最近,我創建了一個簡單的文件加密程序和一個解密程序。 首先,我將一個文件放入FileStream中,並根據密碼更改了文件的每個字節。 這是我的代碼
加密程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
namespace Encrypter
{
class Program
{
static void Main(string[] args)
{
//Actual code starts from here
string file_path = @args[0];
string[] splited_filepath = file_path.Split('\\');
string file_name = splited_filepath[splited_filepath.GetLength(0) - 1];
FileStream file;
if (File.Exists(file_path))
{
file = new FileStream(file_path, FileMode.Open);
if (!file.CanWrite)
{
Console.WriteLine("The file exists, but not writable!");
return;
//goto exit;
}
}
else
{
Console.WriteLine("The file does not exist!\n{0}", file_path);
return;
//goto exit;
}
Console.Write("Enter the password : ");
string password = Console.ReadLine();
if(password == "")
{
Console.WriteLine("Password Cannot be empty!");
return;
}
try
{
while(file.Position < file.Length)
{
int b_input = file.ReadByte();
file.Position--;
file.WriteByte(encrypt_byte(b_input,password,file.Position));
file.Position++;
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
return;
//goto exit;
}
file.Close();
string encrypted_file_name = base64_enc(file_name) + compute_hash(password, new MD5CryptoServiceProvider());
string encrypted_file_path = create_encrypted_file_path(encrypted_file_name, splited_filepath);
try
{
File.Move(file_path, encrypted_file_path);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
//exit:;
}
static string create_encrypted_file_path(string enc_filename, string[] splited_fp)
{
string output = "";
for(int a = 0; a < splited_fp.GetLength(0) - 1; a++)
{
output += (splited_fp[a] + "\\");
}
output += enc_filename;
return output;
}
//Encrypting method starts here
static byte encrypt_byte(int input, string pass, long pos)
{
char[] pass_char = pass.ToArray();
int char_pos = Convert.ToInt32(pos % pass_char.GetLength(0));
byte output = Convert.ToByte(
(input + Convert.ToInt32(pass_char[char_pos])) % 256
);
return output;
}
static string compute_hash(string input,HashAlgorithm algorithm)
{
return BitConverter.ToString(algorithm.ComputeHash(Encoding.UTF8.GetBytes(input)));
}
//base64 encoding method
static string base64_enc(string input)
{
return Convert.ToBase64String(Encoding.UTF8.GetBytes(input));
}
}
}
解密器的代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
namespace Decrypter
{
class Program
{
static void Main(string[] args)
{
//Actual code starts from here
string file_path = args[0];
string[] splited_filepath = file_path.Split('\\');
string file_name = splited_filepath[splited_filepath.GetLength(0) - 1];
string encrypted_filename = file_name.Substring(0, file_name.Length - 47);
string hashed_password = file_name.Substring(file_name.Length - 47);
FileStream file;
if (File.Exists(file_path))
{
file = new FileStream(file_path, FileMode.Open);
if (!file.CanWrite)
{
Console.WriteLine("The file exists, but not writable!");
return;
//goto exit;
}
}
else
{
Console.WriteLine("The file does not exist!\n{0}", file_path);
Console.ReadLine();
return;
//goto exit;
}
Console.Write("Enter the password : ");
string password = Console.ReadLine();
if(password == "")
{
Console.WriteLine("Password cannot be empty!");
return;
}
//Varify the password
if(compute_hash(password,new MD5CryptoServiceProvider()) != hashed_password)
{
Console.WriteLine(compute_hash(password, new MD5CryptoServiceProvider()));
Console.WriteLine(hashed_password);
Console.WriteLine("Invalid password!");
return;
}
try
{
while(file.Position < file.Length)
{
int b_input = file.ReadByte();
file.Position--;
file.WriteByte(decrypt_byte(b_input, password, file.Position));
file.Position++;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
return;
//goto exit;
}
file.Close();
string decrypted_filename = base64_dec(encrypted_filename);
string decrypted_filepath = create_decrypted_file_path(decrypted_filename, splited_filepath);
try
{
File.Move(file_path, decrypted_filepath);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
//exit:;
}
//Decrypting method starts here
static byte decrypt_byte(int input, string pass, long pos)
{
char[] pass_char = pass.ToArray();
int char_pos = Convert.ToInt32(pos % pass_char.GetLength(0));
byte output = Convert.ToByte(
get_output_byte(input - Convert.ToInt32(pass_char[char_pos]))
);
return output;
}
//a simple method to get the numaric value of the output byte
static int get_output_byte(int number)
{
if (number < 0) return 256 + number;
else return number;
}
static string compute_hash(string input, HashAlgorithm algorithm)
{
return BitConverter.ToString(algorithm.ComputeHash(Encoding.UTF8.GetBytes(input)));
}
//base64 decoding method
static string base64_dec(string input)
{
return Encoding.UTF8.GetString(Convert.FromBase64String(input));
}
static string create_decrypted_file_path(string enc_filename, string[] splited_fp)
{
string output = "";
for (int a = 0; a < splited_fp.GetLength(0) - 1; a++)
{
output += (splited_fp[a] + "\\");
}
output += enc_filename;
return output;
}
}
}
問題在於這兩個程序都相當慢,並且需要花費數小時來加密或解密大文件。 有什么建議可以加快這個過程嗎?
這大約是最壞的方式,我能想到的使用FileStream
在一個循環:
int b_input = file.ReadByte();
file.Position--;
file.WriteByte(encrypt_byte(b_input,password,file.Position));
file.Position++;
好吧,第一行還不錯。 第二行使流刷新其寫緩沖區並使它的讀緩沖區無效。 然后,我們寫入一個新字節並再次調整位置,從而導致另一個刷新和無效操作(並導致我們跳過其他所有字節來啟動,因為WriteByte
已更新文件位置)。
一個簡單的解決方案是使用File.ReadAllBytes
並僅在內存中進行操作。 但是,正如您自己觀察到的那樣,這不適用於大文件。
相反,您應該使用大小適當的緩沖區(例如var buffer = new byte[4096];
),然后使用file.Read
讀取塊1中的文件。 最好還可以使用指向第二個文件的單獨流作為寫入側,以便仍可以從兩側的緩沖區中受益。
您必須維護自己在文件中位置的數量,而不是依靠文件的Position
屬性,並且循環應在Read
返回0
時終止(但請確保您始終注意該值並且僅處理該值的大部分)緩沖區)。
最后,關閉兩個流,刪除舊文件並移動/重命名新文件以替換它。
請注意,這種“加密”適用於玩具使用,但不應認真用於任何東西。 您已經知道System.Security.Cryptography
命名空間。 對於任何認真的加密工作,您應該在其中尋找現有的類,而不要自己滾動。
1考慮也使用Async
變量。 大部分時間仍然會花在I / O上 。 在這種情況下阻塞線程不會為系統增加太多價值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.