编写一个计算机程序用来计算一个文件的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();//关闭文件
}
}