C语言和Java中的文件操作对比

本文对比了使用C语言和Java处理文件的具体实现方法,详细介绍了如何读取文本文件,并将特定格式的数据进行拼接处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求:有个同学拿了一堆化学上面催化剂的一些数据让我写个程序处理一下。同学给我的是一个txt文件,里面有很多行数据,每378行分为一组,组与组之间有一行空白行。有的行有5列,有的行只有3列,要求是将从第二组开始的数据按照行号拼接到第一组数据后面,第二组接到第一组后面,第三组接到第二组后面……以此类推。

这个需求听上去其实也不复杂,无非就是对文件的操作,具体的拼接过程完全可以在内存中实现(只要有足够大的内存),C语言忘得都差不多了,借此机会复习一下吧。

先看一下原数据格式:

   1         -0.101783D+02 -0.243955D+01 -0.216450D-04 -0.414976D-03 -0.414376D-14
   2         -0.243955D+01 -0.998679D+00  0.222268D-03  0.393219D-01 -0.263128D-14
   3         -0.216450D-04  0.222268D-03 -0.117000D+00 -0.812384D-03 -0.426587D-15
   4         -0.414976D-03  0.393219D-01 -0.812384D-03 -0.183967D+00  0.764145D-15
   5         -0.414376D-14 -0.263128D-14 -0.426587D-15  0.764145D-15 -0.402880D-03
 
   1         -0.200450D+01 -0.166424D-05  0.176481D-03 -0.485456D-14 -0.935424D+00
   2         -0.107777D+01  0.309533D-03  0.492703D-01  0.101422D-16 -0.604235D+00
   3          0.394986D-03 -0.364537D+00 -0.624885D-03 -0.434795D-15  0.522164D-03
   4          0.610953D-01 -0.667912D-03 -0.456884D+00 -0.162973D-15 -0.507692D-01
   5         -0.153209D-15  0.584723D-15  0.193193D-14 -0.254258D+00 -0.904307D-14
 
   1         -0.936221D+00 -0.933496D+00 -0.240847D-04 -0.281712D-14  0.299125D-15
   2         -0.655863D+00 -0.510790D+00 -0.107102D-02  0.103522D-14 -0.577630D-15
   3         -0.289317D-04  0.126813D-03 -0.907516D-01  0.165825D-15  0.843699D-15
   4          0.144731D+00  0.137608D-01 -0.292953D-04  0.381367D-15 -0.200552D-15
   5         -0.329280D-14 -0.865301D-14  0.111258D-14  0.119046D-03  0.274277D-01
 
   1         -0.166760D-08 -0.650029D-09 -0.164477D-08
   2         -0.482698D-08 -0.166674D-08 -0.497130D-08
   3         -0.270613D-10  0.154384D-09 -0.137192D-09
   4         -0.344229D-09 -0.262246D-09 -0.810262D-09
   5          0.620346D-15  0.223117D-15  0.668207D-16
原始数据比较多,这里就拿一部分举例,数据保存在in.txt文件,输出结果保存在out.txt文件中。

下面上代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// 列数,该数值要足够大保证能存下拼接后的字符串
#define MAX_COL 1000
// 行数
#define ROW 5
// 读取一行数据,在没有遇到回车的情况下最多读取的字符数
#define LENGTH	1024
/*	说明:将需要读取的文件和程序放在同一个文件夹下
		文件名需要和main函数中的一致
		输出文件会自动生成,也在同一个目录下
*/

/*	函数功能: 去掉一行前面的行号和空格
	如果第一个非空格字符不是负号则添加一个空格方便对齐
*/
int trim(char* buffer)
{
	int i=0;
	int count=0;
	for(i=0;count<=2;i++)
	{
		if(count==0&&buffer[i]!=' ')
		{
			count=1;
		}
		else if(count==1&&buffer[i]==' ')
			count=2;
		else if(count==2&&buffer[i]!=' ')
			return (buffer[i]!='-')?i-1:i;	
	}
	return 0;
}
/*	函数功能:将缓存中的一行数据追加到数组中对应行
	函数返回追加后数组中这一行字符串末尾的下标,方便下次查找
	参数值:data是一个动态二维数组,用于缓存全部数据
			buffer是缓存的一行数据
			row行号
			len[]保存的是追加前data数组中第row行字符串结尾处的下标,追加后会更新对应的值
*/
int append(char* data,char* buffer,int row,int len[])
{
	// 根据行号,找到数组中这一行字符串的末尾的下标
	int i=len[row];
	int j;
	int begin=0;
	// 判断是第几组数据
	// 如果不是第一组则去掉行号和前面多余的空格
	// 如果第一个非空格字符不是负号则添加一个空格方便对齐
	if(i!=0)
	{
		begin=trim(buffer);
	}
	
	// 去掉buffer中的换行符
	if(buffer[strlen(buffer)-1]=='\n')
	{
		buffer[strlen(buffer)-1]='\0';
	}
	// 将最后的'\0'换成空格
	if(data[row*MAX_COL+i]=='\0')
	{
		data[row*MAX_COL+i]=' ';
		i++;
	}
	// 循环将buffer中的字符复制到data中	
	for(j=begin;buffer[j]!='\0';i++,j++)
	{
		data[row*MAX_COL+i]=buffer[j];
	}
	// data中字符串结尾添加'\0'
	data[row*MAX_COL+i]='\0';
	return i;
}
/*	函数功能:读取文件中一行数据

*/
char* read(char* buffer,FILE* fp)
{
	return fgets(buffer,MAX_COL,fp);
}
/*  函数功能:判断某一行是不是空白行
	如果是返回0,否则返回1
*/
int isEmptyLine(char* buffer)
{
	int i=0;
	for(i=0;buffer[i]!='\0';i++)
	{
		// 只要碰到非空格或回车,就返回1
		if(buffer[i]!=' '&&buffer[i]!='\n')
			return 1;
	}
	// 为空白行,返回0
	return 0;
}

main()
{	
	FILE* fp;
	FILE* out;
	
	char* data;
	char* buffer;
	// 保存data数组每一行字符串的结尾下标
	int len[ROW];
	// 行号和组号,每5行为一组
	int row_num=0;
	
	int i;

	// 打开源文件
	fp=fopen("in.txt","r");
	// 输出文件
	out=fopen("out.txt","a");
	// 二维数组保存数据
	// 这里申请的是动态二维数组
	data=(char*)calloc(ROW*MAX_COL,sizeof(char));
	// 临时保存读取到的一行数据
	buffer=(char*)malloc(LENGTH*sizeof(char));
	// 初始化len数组
	for(i=0;i<ROW;i++)
	{
		len[i]=0;
	}
	// 检查文件有没有打开成功
	if(fp==NULL)
	{
		printf("cannot open");
		return-1;
	}
	// 检查动态内存有没有申请成功
	if(data==NULL)
	{
		printf("cannot calloc memory for data");
		return -1;
	}
	if(buffer==NULL)
	{
		printf("cannot calloc memory for buffer");
		return -1;
	}
	// feof(char* cp)函数是用来判断是否到文件尾的
	// 如果是文件尾,返回非0值
	while(feof(fp)==0)
	{
		// 读取一行数据,存到缓存
		read(buffer,fp);
		// 如果是空白行则跳过
		if(isEmptyLine(buffer)==0)
		{
			continue;
		}
		// 将读取到的一行数据追加到data数组对应行
		len[row_num]=append(data,buffer,row_num,len);

		row_num++;
		// 判断一组有没有读完
		// 如果读完一组,则将行号重置,组号加1
		if(row_num==ROW)
		{
			row_num=0;
		}
	}
	// 将数组中保存的字符串输出到文件
	for(i=0;i<ROW;i++)
	{
		fputs(&data[i*MAX_COL],out);
		fputs("\n",out);
	}

	// 释放动态内存
	free(buffer);
	buffer=NULL;
	free(data);
	data=NULL;
	// 关闭文件
	fclose(fp);
	fclose(out);
	fp=NULL;
	out=NULL;

	return 0;
}
其实这里面文件操作并不复杂,复杂在对字符串的处理,这也是C语言不方便的地方,需要小心一些隐藏的字符,如‘\0','\n',' '等。

下面再用Java实现一下,对比C的代码要简单很多:

package mp1;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Data
{
	private static final int LINE_SUM=5;
	public static void main(String[] args) throws IOException
	{
		
		// 输出文件
		File outFile=new File("out.txt");
		FileWriter fWriter=new FileWriter(outFile, false);
		// 读取文件
		FileReader fReader=new FileReader("in.txt");
		BufferedReader br=new BufferedReader(fReader);
		
		StringBuilder[] data=new StringBuilder[LINE_SUM];
		String buffer=null;
		int seq=0;
		int group=1;
		while((buffer=br.readLine())!=null)
		{
			// 跳过空白行
			if(!buffer.trim().equals(""))
			{
				// 如果是第一组,直接存入数组
				if(group==1)
				{
					data[seq]=new StringBuilder("");
					data[seq].append(buffer);
					
				}
				// 其他组
				else
				{
					// 获取序号,判断应该存入哪一行
					String trimedBuffer=buffer.trim();
//					System.out.println(trimedBuffer);
					
					// 去掉序号
					buffer=trimedBuffer.substring(trimedBuffer.indexOf(" ")).trim();
					// 判断第一串数字有没有负号
					// 如果没有负号则在开头添加一个空格,方便对齐
					if(!(buffer.charAt(0)=='-'))
					{
						buffer=" "+buffer;
					}
					// 追加到对应的行
					data[seq].append(" "+buffer);
				}
				// 序号加1
				seq++;
				// 一组读取完毕,序号重置,组号加1
				if(seq==LINE_SUM)
				{
					seq=0;
					group++;
				}
			}
		}
		// 将数组中的数据写入文件
		for(int i=0;i<data.length;i++)
		{
			fWriter.write(data[i].toString()+"\n");
		}
		System.out.println("group="+(group-1));
		fWriter.close();
		fReader.close();
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值