編寫一個計算機程序用來計算一個文件的16位效驗和。最快速的方法是用一個32位的整數來存放這個和。記住要處理進位(例如,超過16位的那些位),把它們加到效驗和中。
要求:1)以命令行形式運行:check_sum infile
其中check_sum爲程序名,infile爲輸入數據文件名。
2)輸出:數據文件的效驗和
附:效驗和(checksum)
參見RFC1071 - Computing the Internet checksum
原理:把要發送的數據看成16比特的二進制整數序列,並計算他們的和。若數據字節長度爲奇數,則在數據尾部補一個字節的0以湊成偶數。
例子:16位效驗和計算,下圖表明一個小的字符串的16位效驗和的計算。
爲了計算效驗和,發送計算機把每對字符當成16位整數處理並計算效驗和。如果效驗和大於16位,那麼把進位一起加到最後的效驗和中。
目的:體驗多種語言不同效果
c++的2個版本
版本三:python版本check_sum.py
命令行輸入:python check_sum.py filePath
import sys # 爲了讀取命令行的信息
import os.path # 判斷是否存在文件
CONST_VALUE = int('0x10000', 16)
def calculate(filePath):
if not os.path.isfile(filePath):
print("該地址不存在")
else:
try:
infile = open(filePath, 'rb')
except IOError:
print("Something wrong about File " + filePath + "happens..Try again.")
time = 0
print('文本中讀取的內容如下:')
all_num_lst = ""
for i in infile.read():
print(chr(i), ":", hex(i), end=" ")
time += 1
temp_str = str(hex(i)).replace("0x","")
if len(temp_str) == 1: # ascill碼小於16時
temp_str = '0' + temp_str
if time % 2 == 1 and time > 1: # 把整數轉換成int類型後再轉字符類型去掉0x標誌
all_num_lst = all_num_lst + "-" + temp_str # 加上-符號區分2個16字節組合
else:
all_num_lst = all_num_lst + temp_str
if time % 5 == 0: # 控制每行5個數據
print('\n')
print("十六位校驗:", all_num_lst)
if time % 2 == 1:
print("數據字節長度爲奇數,數據尾部補一個字節的0以湊成偶數")
all_num_lst = all_num_lst + "00" # 補00字符
else:
print("數據字節長度爲偶數")
print("十六位校驗:", all_num_lst)
all_num_lst = "0x" + all_num_lst
all_num_lst = all_num_lst.replace("-", "-0x")
sum = 0
for n in all_num_lst.split('-'):
sum = sum + int(n, 16)
carry = int(sum / CONST_VALUE) # 求值後爲int類型,對0x10000求,表示爲進位
result = int(sum % CONST_VALUE) + carry #
print("校驗和爲:", hex(result))
infile.close()
def main():
# filePath = sys.argv[1].strip() # 因爲在命令行使用python文件的時候是 python check_sum.py filePath,sys.argvshi從python後開始的元素
filePath = r"C:\Users\Lenovo\Desktop\1.txt" # 測試時使用的地址
calculate(filePath)
if __name__ == "__main__":
main()
版本四:java版本
javac check_sum.java
java check_sum filePath
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class check_sum {
public static void main(String infile1[]) throws IOException {
String[] infile=new String[1];
infile[0]="C:\\Users\\Lenovo\\Desktop\\1.txt";//需要用命令行的時候這裏刪掉
// TODO Auto-generated method stub
InputStream inputStream=null;//輸入流
int data;//讀取到的一個字節
int sum=0;//計算十六進制的個數
final int Ox10000=Integer.parseInt("10000",16);//十六進制10000對應的十進制數值
StringBuffer buffer=new StringBuffer();
inputStream=new FileInputStream(infile[0]);//打開文件
System.out.println("文本中讀取的內容如下:");
while((data=inputStream.read())!=-1){
sum++;
if(sum%2==1&& sum >1)
buffer.append("-");
String hex=Integer.toHexString(data);//十進制轉十六進制
System.out.print((char)data+":Ox"+hex+"\t");//輸出
if(sum%5==0)
System.out.println();//每行輸出五個
if(hex.length()==2)
buffer.append(hex);
//若字節的ASCII小於16,則填充0
else{
buffer.append("0");
buffer.append(hex);
}
}
System.out.println("\n"+buffer.toString());
//若數據字節長度爲奇數,則在數據尾部補一個字節的0以湊成偶數。
if(sum%2==1){
System.out.println("\r數據字節長度爲奇數,數據尾部補一個字節的0以湊成偶數");
buffer.append("00");
}else{
System.out.println("\r數據字節長度爲偶數");
}
System.out.println(buffer.toString());
String segments[]=new String(buffer).split("-");//得到多個十六進制的數值
System.out.println("十六位的數值如下:");
for(String segment:segments)
System.out.print(segment+"\t");
System.out.println();
int decimal;
int result=0;//保存相加後的結果
for(String segment:segments){
decimal=Integer.parseInt(segment,16);
result+=decimal;//累加
}
int carry=result/Ox10000;//進位位
String hex=Integer.toHexString(result%Ox10000+carry);
System.out.println("\r校驗和爲:Ox"+hex);
inputStream.close();//關閉文件
}
}