Linux C/C++ 实现网络流量分析(性能工具)

news2024/12/23 13:29:54

网络流量分析的原理基于对数据包的捕获、解析和统计分析,通过对网络流量的细致观察和分析,帮助管理员了解和优化网络的性能、提高网络安全性,并快速排查和解决网络故障和问题。

Linux中的网络流量常见类型
在Linux中,网络流量可以分为几种不同的类型。以下是一些常见的网络流量类型:

  1. TCP流量:TCP(传输控制协议)是一种可靠的、面向连接的协议。TCP流量通常用于传输可靠的数据,例如网页浏览、文件传输等。

  2. UDP流量:UDP(用户数据报协议)是一种无连接的协议,不保证数据的可靠性和顺序。UDP流量通常用于实时应用,如VoIP(网络电话)、视频流传输等。

  3. ICMP流量:ICMP(Internet控制消息协议)用于传输网络控制消息和错误报告。ICMP流量通常用于网络故障排查、Ping命令等。

  4. HTTP流量:HTTP(超文本传输协议)是一种应用层协议,用于在Web浏览器和服务器之间传输数据。HTTP流量通常用于网页浏览、下载文件等Web应用。

  5. HTTPS流量:HTTPS是HTTP的安全版本,使用SSL(安全套接字层)或TLS(传输层安全)协议加密通信。HTTPS流量通常用于安全的Web传输,例如在线银行、电子商务等。

  6. DNS流量:DNS(域名系统)用于将域名与IP地址相互映射。DNS流量通常用于解析域名、获取IP地址等。

  7. FTP流量:FTP(文件传输协议)用于在客户端和服务器之间传输文件。FTP流量通常用于文件上传、下载等。

  8. SSH流量:SSH(安全壳层)是一种加密的网络协议,用于安全和远程登录。SSH流量通常用于安全的远程管理和文件传输。

这些网络流量类型在不同的应用场景和协议中扮演着不同的角色。分析和监控不同类型的网络流量可以帮助管理员了解网络使用情况、排查故障并优化网络性能。

Linux下监控网络流量的目的
Linux下监控网络流量的目的有多个:

  1. 网络性能优化:监控网络流量可以帮助管理员了解网络的使用情况和瓶颈,以便进行性能优化和提高网络效率。

  2. 安全性增强:通过监控网络流量,可以及时发现异常的网络流量,如DDoS攻击、恶意软件传播等,以便及时采取相应的防御措施。

  3. 资源管理:监控网络流量可以帮助管理员了解各个主机或设备的网络使用情况,对网络资源进行分配和管理,以避免某个用户或设备占用过多的带宽和资源导致其他用户或设备受到影响。

  4. 计费和成本控制:监控网络流量可以帮助提供网络服务的机构或企业对用户的网络使用情况进行计费和成本控制,确保网络资源的合理利用和节约成本。

  5. 故障排查和问题定位:通过监控网络流量,可以及时发现网络故障、问题和异常,辅助管理员进行故障排除和问题定位,以减少网络停机时间和降低维护成本。

总而言之,监控网络流量可以提高网络性能、保障网络安全、管理网络资源、控制成本和故障排查,对于维护良好的网络运行非常重要。

有哪些专门的工具和技术分析网络流量

要实现Linux上的网络流量分析,可以使用一些专门的工具和技术。下面是一些常用的方法和原理:

  1. 使用抓包工具:在Linux上,可以使用像tcpdump、Wireshark这样的抓包工具来捕获网络数据包。这些工具可以监听网络接口,并将捕获到的数据包保存到文件中进行分析。

  2. 使用流量监控工具:像ntop、iftop、bmon等工具可以实时监控网络接口的流量情况,并提供统计信息和图形化展示。

  3. 分析捕获的数据包:捕获到的数据包可以使用Wireshark等工具进行解析和分析。Wireshark可以显示捕获的数据包的详细信息,如源IP地址、目的IP地址、协议类型、端口等,并提供过滤机制来筛选感兴趣的数据。

  4. 使用流量分析工具:除了抓包工具和流量监控工具,还有一些专门用于网络流量分析的工具,如tcpflow、Bro等。这些工具可以解析并分析网络流量中的各种协议,提供更深入的网络流量分析功能。

这些工具的实现原理都涉及到网络协议、socket编程、数据包的捕获和解析等知识。具体来说,抓包工具通过监听网络接口,将接收到的数据包保存到文件中;流量监控工具通过读取接口的流量数据并进行统计和展示;数据包分析工具和流量分析工具则依靠网络协议和数据包的解析来提供更深入的分析功能。

总体来说,实现网络流量分析需要一定的网络知识和编程技巧,同时需要使用相关工具和技术进行数据的捕获、解析和分析。

在Linux文件系统的/proc目录下分析网络流量

在Linux文件系统的/proc目录下,可以找到一些与网络流量相关的信息。以下是一些常见的文件和目录:

  1. /proc/net/dev:这个文件提供了网络设备的收发网络流量统计信息,包括每个网络接口的接收和发送数据包数量、错误统计、丢弃的数据包数量等。
    使用cat或者less命令:你可以使用cat或者less命令来查看/proc下的文件内容,例如:cat /proc/net/dev可以查看网络设备的收发网络流量统计信息。
    使用awk或者sed命令进一步处理:你可以使用awk或者sed命令来处理和过滤数据,例如:cat /proc/net/dev | awk '{print $1, $2}'可以只打印出网络设备名称和接收流量的统计值.
    在这里插入图片描述

  2. /proc/net/tcp:这个文件提供了当前TCP连接的详细信息,包括本地和远程IP地址、端口号,连接状态,以及一些统计信息。
    使用grep命令筛选:你可以使用grep命令来筛选你感兴趣的信息,例如:grep "ESTABLISHED" /proc/net/tcp可以查看当前所有TCP连接中状态为ESTABLISHED的连接信息。

  3. /proc/net/udp:类似于/proc/net/tcp文件,提供了当前UDP连接的详细信息。

  4. /proc/net/raw:提供了当前原始套接字(RAW socket)的相关信息,包括本地和远程IP地址、协议类型等。

  5. /proc/net/snmp:提供了简单网络管理协议(SNMP)相关的统计信息,包括接口、IP、TCP、UDP等各层的统计信息。

  6. /proc/net/ip_conntrack:如果系统启用了连接跟踪(conntrack)功能,这个文件提供了关于当前连接的跟踪信息,包括连接状态、源IP地址、目的IP地址、端口号等。

这些文件提供了一些基本的网络流量统计和连接信息,可以通过读取这些文件进行分析和监控。想要更加深入和详细地分析网络流量,则需要使用更专业的网络流量分析工具。

Linux C/C++ 网络流量分析

代码中网络流量分析是一个用于网络统计的命令行工具,用于监视系统网络接口的流量、带宽使用情况以及与网络相关的统计数据。它可以提供网络传输的各种统计信息,包括数据包的数量、字节数、错误、丢包等。

/*
 * 接口统计信息
 */
typedef struct nic_stats {
	struct timeval tv;		/* tv_sec, tv_usec */
	uint64_t rbytes;		/* total read bytes */
	uint64_t wbytes;		/* total written bytes */
	uint64_t rpackets;		/* total read packets */
	uint64_t wpackets;		/* total written packets */
	uint64_t ierr;			/* total input errors */
	uint64_t oerr;			/* total output errors */
	uint64_t coll;			/* total collisions */
	uint64_t nocp;			/* total nocanput */
	uint64_t defer;			/* total defers */
	uint64_t sat;			/* saturation value */
} nicstats_t;

/*
 * print_header - 打印标题行
 */
static void
print_header(void)
{
	if (g_style)
		(void) printf("%8s %5s %14s %14s\n",
		    "Time", "Int", "rKb/s", "wKb/s");
	else
		(void) printf(
		    "%8s %5s %7s %7s %7s %7s %7s %7s %7s %7s\n",
		    "Time", "Int", "rKb/s", "wKb/s", "rPk/s",
		    "wPk/s", "rAvs", "wAvs", "%Util", "Sat");
}

static int split_ifname(char *if_name, char *drv, uint32_t *instance)
{
...
	n = 0;
	for (p = if_name; *p; p++)
		n++;
	if (n <= 1)
		return (B_FALSE);
	m = n;
	for (p--; isdigit(*p); p--)
		n--;
	if (m == n || n == 0)
		return (B_FALSE);
	(void) strncpy(drv, if_name, n);
	drv[n] = '\0';
	*instance = (uint32_t)atol(++p);
...
}
...
static void update_ksp_by_type(kstat_t **kspp, uint32_t types, char *name)
{
...

	if (types & KS_LINK) 
	{
		*kspp = fetch_ksp("link", 0, name);
		return;
	}
	(void) split_ifname(name, drv, &instance);
	if (types & KS_DRV_MAC) 
	{
		*kspp = fetch_ksp(drv, instance, "mac");
		return;
	}
	if (types & KS_DIN) 
	{
		*kspp = fetch_ksp(drv, instance, name);
		return;
	}
	if (types & KS_DRV) {
		*kspp = fetch_ksp(drv, instance, NULL);
		return;
	}
	if (types & KS_NAME) {
		*kspp = fetch_ksp(name, -1, NULL);
		return;
	}
	...
}
static void update_stats(void)
{
...

	(void) gettimeofday(&now_tv, NULL);

	if (g_tcp) 
	{
		/* 更新TCP统计信息 */
		if (g_new_kstat_chain) 
		{
			g_tcp_ksp = kstat_lookup(g_kc, "tcp", -1, "tcp");
			if (! g_tcp_ksp)
				die(1, "kstat_lookup");
		}
		if (kstat_read(g_kc, g_tcp_ksp, NULL) < 0)
			die(1, "kstat_read");
		g_tcp_new->tv.tv_sec = now_tv.tv_sec;
		g_tcp_new->tv.tv_usec = now_tv.tv_usec;
		TCP_UPDATE(inDataInorderSegs, "inDataInorderSegs");
		TCP_UPDATE(outDataSegs, "outDataSegs");
		TCP_UPDATE(inDataInorderBytes, "inDataInorderBytes");
		TCP_UPDATE(inDataUnorderSegs, "inDataUnorderSegs");
		TCP_UPDATE(inDataUnorderBytes, "inDataUnorderBytes");
		TCP_UPDATE(outDataBytes, "outDataBytes");
		TCP_UPDATE(estabResets, "estabResets");
		TCP_UPDATE(outRsts, "outRsts");
		TCP_UPDATE(attemptFails, "attemptFails");
		TCP_UPDATE(retransBytes, "retransBytes");
		TCP_UPDATE(passiveOpens, "passiveOpens");
		TCP_UPDATE(activeOpens, "activeOpens");
		TCP_UPDATE(halfOpenDrop, "halfOpenDrop");
		TCP_UPDATE(listenDrop, "listenDrop");
		TCP_UPDATE(listenDropQ0, "listenDropQ0");
	}
	if (g_udp) 
	{
		/* 更新UDP统计信息 */
		if (g_new_kstat_chain) 
		{
			g_udp_ksp = kstat_lookup(g_kc, "udp", -1, "udp");
			if (! g_udp_ksp)
				die(1, "kstat_lookup");
		}
		if (kstat_read(g_kc, g_udp_ksp, NULL) < 0)
			die(1, "kstat_read");
		g_udp_new->tv.tv_sec = now_tv.tv_sec;
		g_udp_new->tv.tv_usec = now_tv.tv_usec;
		UDP_UPDATE(inDatagrams, "inDatagrams");
		UDP_UPDATE(outDatagrams, "outDatagrams");
		UDP_UPDATE(inErrors, "inErrors");
		UDP_UPDATE(outErrors, "outErrors");
	}

	if (g_style == STYLE_NONE && ! g_list)
		return;

	/* 更新接口统计信息 */
	for (nicp = g_nicdatap; nicp; nicp = nicp->next) 
	{
		if (! (nicp->flags & NIC_UP))
			/* 链接未打开 */
			continue;
		if (g_nonlocal && (nicp->flags & NIC_LOOPBACK))
			continue;
		if (! (nicp->flags & NIC_OK_UPDATED))
			if (kstat_read(g_kc, nicp->op_ksp, NULL) < 0)
				die(1, "kstat_read");
		/* 保存网络值 */
		nicp->new.tv.tv_sec = now_tv.tv_sec;
		nicp->new.tv.tv_usec = now_tv.tv_usec;
		nicp->new.rbytes =
			fetch6432(nicp->op_ksp, "rbytes64", "rbytes", 0);
		nicp->new.wbytes =
			fetch6432(nicp->op_ksp, "obytes64", "obytes", 0);
		nicp->new.rpackets =
			fetch6432(nicp->op_ksp, "ipackets64", "ipackets", 0);
		nicp->new.wpackets =
			fetch6432(nicp->op_ksp, "opackets64", "opackets", 0);
		switch (g_style) 
		{
		case STYLE_EXTENDED_PARSEABLE:
		case STYLE_EXTENDED:
			nicp->new.ierr = fetch32(nicp->op_ksp, "ierrors", 0);
			nicp->new.oerr = fetch32(nicp->op_ksp, "oerrors", 0);
			/*FALLTHROUGH*/
		case STYLE_FULL:
		case STYLE_SUMMARY:
			nicp->new.coll = fetch32(nicp->op_ksp, "collisions",
				0);
			nicp->new.nocp = fetch_nocanput(nicp->op_ksp, 0);
			nicp->new.defer = fetch32(nicp->op_ksp, "defer_xmts",
				0);
			nicp->new.sat = nicp->new.defer + nicp->new.nocp +
				nicp->new.coll;
			nicp->new.sat += fetch32(nicp->op_ksp, "noxmtbuf", 0);
			break;
		}
		nicp->speed = fetch64(nicp->op_ksp, "ifspeed", 0);
		nicp->duplex = fetch32(nicp->op_ksp, "link_duplex", 0);
	}
...
}
static void load_snmp(FILE *snmp)
{
...

	/* 从/proc/net/snmp加载TCP和/或UDP统计信息 */
...
	while (remaining) 
	{
		p = fgets(buf, sizeof (buf), snmp);
		if (! p)
			break;
		if (g_tcp && strncmp("Tcp: RtoAlgorithm RtoMin RtoMax MaxConn "
				"ActiveOpens PassiveOpens AttemptFails "
				"EstabResets CurrEstab InSegs OutSegs "
				"RetransSegs InErrs OutRsts", p, 141) == 0) 
				{
			int n;
			n = fscanf(snmp, "Tcp: %lld %lld %lld %lld "
			    "%lld %lld %lld %lld %lld %lld "
			    "%lld %lld %lld %lld\n",
			    &ll[0], &ll[1], &ll[2], &ll[3],
			    &ll[4], &ll[5], &ll[6], &ll[7],
			    &ll[8], &ll[9], &ll[10], &ll[11],
			    &ll[12], &ll[13]);
			if (n == 14) 
			{
				g_tcp_new->inDataInorderSegs = ll[9];
				g_tcp_new->outDataSegs = ll[10];
				g_tcp_new->estabResets = ll[7];
				g_tcp_new->outRsts = ll[13];
				g_tcp_new->attemptFails = ll[6];
				/* Note: bytes */
				g_tcp_new->retransBytes = ll[11];
				g_tcp_new->passiveOpens = ll[5];
				g_tcp_new->activeOpens = ll[4];
			}
			remaining--;
		} 
		else if (g_udp && strncmp("Udp: InDatagrams NoPorts "
				"InErrors OutDatagrams RcvbufErrors "
				"SndbufErrors\n", p, 72) == 0) 
				{
			int n;
			n = fscanf(snmp, "Udp: %lld %lld %lld %lld "
			    "%lld %lld\n",
			    &ll[0], &ll[1], &ll[2], &ll[3],
			    &ll[4], &ll[5]);
			if (n == 6) 
			{
				g_udp_new->inDatagrams = ll[0];
				g_udp_new->outDatagrams = ll[3];
				g_udp_new->inErrors = ll[2]; /* + ll[4]? */
				g_udp_new->outErrors = ll[5];
			}
			remaining--;
		}
	}
}
...
static void update_timestr(time_t *tptr)
{
...

	if (tptr)
		t = *tptr;
	else
		t = time(NULL);
	tm = localtime(&t);
	(void) strftime(g_timestr, sizeof (g_timestr), "%H:%M:%S", tm);
}

static void sleep_for(hrtime_t period, hrtime_t start_n)
{
...
	do 
	{
		pause_tv.tv_sec = pause_n / NANOSEC;
		pause_tv.tv_nsec = pause_n % NANOSEC;
		status = nanosleep(&pause_tv, (struct timespec *)NULL);
		if (status < 0)
			if (errno == EINTR)
			 {
				now_n = gethrtime();
				pause_n = start_n + period - now_n;
				if (pause_n < 100)
					return;
			}
			 else 
			{
				...
			}
	} while (status != 0);
}
...

If you need the complete source code, please add the WeChat number (c17865354792)

运行结果:


Time列:表示当前采样的响应时间.
Int: 网卡名称.
rKB/s : 每秒接收到千字节数.
wKB/s : 每秒写的千字节数.
rPk/s : 每秒接收到的数据包数目.
wPk/s : 每秒写的数据包数目.
rAvs : 接收到的数据包平均大小.
wAvs : 传输的数据包平均大小.
%Util : 网卡利用率(百分比).
Sat : 网卡每秒的错误数.网卡是否接近饱满的一个指标.尝试去诊断网络问题的时候,推荐使用-x选项去查看更多的统计信息.

这将显示ens33接口的流量、带宽使用情况以及其他统计数据:
监控所有网络接口的统计信息,同时显示TCP和UDP连接相关的统计信息:

总结

网络流量分析需要一定的技术知识和经验,但通过学习和实践,我们可以掌握这个技能,更好地管理和维护网络环境。

Welcome to follow WeChat official account【程序猿编码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1148208.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数组与链表算法-链表与多项式

目录 数组与链表算法-链表与多项式 多项式链表表示法 C代码 数组与链表算法-链表与多项式 使用链表的最大好处就是减少内存的浪费&#xff0c;并且能增加使用上的弹性。例如数学上常用的多项式表示法&#xff0c;虽然可以使用数组方式来处理&#xff0c;但当数据内容变动时…

AC修炼计划(AtCoder Regular Contest 164)

传送门&#xff1a;AtCoder Regular Contest 164 - AtCoder A.签到题&#xff0c;在此不做赘述 B - Switching Travel 这题本来该是秒的&#xff0c;但是因为没有考虑清楚环的问题而被卡半天&#xff0c;其实我们不难发现&#xff0c;要想使题目存在节点&#xff0c;就得让该节…

【PC电脑windows-学习样例generic_gpio-ESP32的GPIO程序-基础样例学习】

【PC电脑windows-学习样例generic_gpio-ESP32的GPIO程序-基础样例学习】 1、概述2、实验环境3、 物品说明4、自我总结5、本次实验说明6、实验过程&#xff08;1&#xff09;复制目录到桌面&#xff08;2&#xff09;手动敲写&#xff08;3&#xff09;反复改错&#xff08;4&am…

将知识图谱结合到地铁客流预测中:一个分散注意力关系图卷积网络

导读 论文题目《Combining knowledge graph into metro passenger flow prediction: A split-attention relational graph convolutional network 》。该论文于2023年发表于《Expert Systems With Applications》&#xff0c;文章基于知识图谱&#xff0c;提出了一种分割注意力…

【操作系统】考研真题攻克与重点知识点剖析 - 第 1 篇:操作系统概述

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

数组元素逆序交换

数组元素逆序交换 例如&#xff1a; 输入&#xff1a; 1,2,3,4,5 输出&#xff1a; 5,4,3,2,1 代码&#xff1a; #include<stdio.h> #define N 5 int main() {int a[N], i, temp;for (i 0; i < N; i) {scanf("%d", &a[i]);}for (i 0; i < N…

FL Studio 21.2 升级,支持 Stem 分离和可以发布音乐的 FL Cloud

FL Studio 21.2 带有 stem 分离和 FL Cloud&#xff0c;这是一项专为 FL Studio 打造的具有里程碑意义的新服务。其他新功能包括 FL Studio Fruity Edition 的 Audio Clips&#xff08;音频剪辑&#xff09;和一个新的模拟建模合成器 Kepler。 fl studio 21直装版: https://pan…

JavaEE-cookie和session

本部分内容包括 cookie基本概念&#xff0c;sendcookies和getcookies代码&#xff1b; session基本概念&#xff0c;session实现登陆界面&#xff1b; 上述过程中涉及的代码如下&#xff1a; 1 import javax.servlet.ServletException; import javax.servlet.annotation.WebSe…

2318.不同骰子序列的数目

经典的DP题目&#xff0c;求方案数 从序列中最后一个数字往前考虑 当前状态取决于前一个的状态和再前一个的状态所以dp&#xff08;n&#xff0c;last&#xff0c;last1&#xff09;为当前考虑的是第n个并且前一个数字是last 再前一个数字是last1的所有方案数&#xff0c;递归的…

Leetcode—21.合并两个有序链表【简单】

2023每日刷题&#xff08;十三&#xff09; Leetcode—21.合并两个有序链表 直接法实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* mergeTwoLists(struct ListNode* list1, struct…

0033Java程序设计-基于java的NBA球队运营管理系统的的设计与实现论文

文章目录 摘 要目 录系统设计开发环境 摘 要 本NBA球队运营管理系统设计目标是实现NBA球队运营管理的信息化管理&#xff0c;提高管理效率&#xff0c;使得NBA球队运营管理工作规范化、科学化、高效化。 本文研究的NBA球队运营管理系统基于SSM架构&#xff0c;采用JSP技术、J…

python爬虫selenium和ddddocr使用

python爬虫selenium和ddddocr使用 selenium使用 selenium实际上是web自动化测试工具&#xff0c;能够通过代码完全模拟人使用浏览器自动访问目标站点并操作来进行web测试。 通过pythonselenium结合来实现爬虫十分巧妙。 由于是模拟人的点击来操作&#xff0c;所以实际上被反…

一天掌握python爬虫【基础篇】 涵盖 requests、beautifulsoup、selenium

大家好&#xff0c;我是python222小锋老师。前段时间卷了一套 Python3零基础7天入门实战 以及1小时掌握Python操作Mysql数据库之pymysql模块技术 近日锋哥又卷了一波课程&#xff0c;python爬虫【基础篇】 涵盖 requests、beautifulsoup、selenium&#xff0c;文字版视频版。1…

[java/力扣110]平衡二叉树——优化前后的两种方法

分析 根据平衡二叉树的定义&#xff0c;只需要满足&#xff1a;1、根节点两个子树的高度差不超过1&#xff1b;2、左右子树都为平衡二叉树 代码 public class BalancedBinaryTree {public class TreeNode{int val;TreeNode left;TreeNode right;TreeNode(){}TreeNode(int va…

基于SSM的n省出口基地公共信息服务平台设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

软考下午第一题 案列分析

期待分值 10&#xff0c;前三问12左右分&#xff0c;最后一题2、3分左右&#xff0c;重点在于拿下前面三题。 小心谨慎&#xff0c;不要大意。 数据流图 外部系统 数据存储 加工&#xff08;&#xff09;process 数据流 第二小题 说明给出存储名称&#xff0c;就使用该名称&…

C# Socket通信从入门到精通(6)——单个同步TCP服务器监听多个客户端C#代码实现

前言: 我们在C# Socket通信从入门到精通(5)——单个同步TCP服务器监听一个客户端C#代码实现这篇文章中讲述了一个服务器如何与一个客户端进行交互,但是有时候我们需要一个服务器与多个客户端进行交互,这时候上一篇文章介绍的方法就不足以实现这个功能,本篇文章就是介绍如…

基于Qt 文本读写(QFile/QTextStream/QDataStream)实现

​ 在很多时候我们需要读写文本文件进行读写,比如写个 Mp3 音乐播放器需要读 Mp3 歌词里的文本,比如修改了一个 txt 文件后保存,就需要对这个文件进行读写操作。本章介绍简单的文本文件读写,内容精简,让大家了解文本读写的基本操作。 ## QFile 读写文本 QFile 类提供了读…

[2021]不确定成本下的处理分配

英文题目&#xff1a;Treatment Allocation under Uncertain Costs 中文题目&#xff1a;不确定成本下的处理分配 单位&#xff1a;swager、uber 时间&#xff1a;2021 论文链接&#xff1a;https://arxiv.org/pdf/2103.11066.pdf 代码&#xff1a; 摘要&#xff1a; 我…

一个基于Excel模板快速生成Excel文档的小工具

介绍 DocumentGenerator是一个Excel快速生成工具&#xff0c;目标以后还能实现Word、pdf等的文件的生成。该程序独立运行&#xff0c;可通过HTTP接口调用其生成接口。 典型使用场景为如下&#xff1a; 使用者编写模板文件使用者准备模板文件的填充JSON数据内容使用者通过网络…