JMeter - 函数之CSVRead
作用:与配置元件CSV Data Set Config 作用一致:做参数化时可以使用
生成函数:

csv文件数据:
nick,18811111112,123456
xiaoming,18811111111,123456
zhangsna,18811111113,123456
在json上送请求体中引用csv数据:
{ "username":"${__CSVRead(C:\Users\86158\Desktop\jmx\csv\add_user.csv,0)}",
"mobile":"${__CSVRead(C:\Users\86158\Desktop\jmx\csv\add_user.csv,1)}",
"workNumber":"${__CSVRead(C:\Users\86158\Desktop\jmx\csv\add_user.csv,2)}"}
结果:

注意:
CSVRead函数:
csv 中有三行数据,每行数据为一次http接口请求,
线程组-线程数需要设置为3,循环次数设置为1 ,才能依次循环取到每行数据.
线程组-线程数需要设置为1,循环次数设置为3,只能读到第一行数据
CSV DATA SET CONFIG :
线程组-线程数需要设置为3,循环次数设置为1
线程组-线程数需要设置为1,循环次数设置为3
都能循环读到数据
Jmeter http 取样器怎么 使用CSV 函数读取 csv 文件中的信息
在 JMeter 中,除了使用 CSV Data Set Config 元件外,还可以通过内置的 __CSVRead() 函数 来读取 CSV 文件中的数据。这种方式更灵活(例如可以在同一个线程中多次读取不同列、手动控制读取行等),但使用稍复杂。
✅ 一、__CSVRead() 函数基本语法
${__CSVRead(filename.csv, column_index)}
filename.csv:CSV 文件路径(相对路径基于 JMeter 的bin目录,建议用绝对路径)column_index:从 0 开始的列索引(第1列是0,第2列是1,以此类推)
⚠️ 注意:
__CSVRead()不会自动换行!你需要配合${__CSVRead(filename.csv,next)}手动“翻页”。
✅ 二、使用步骤(完整示例)
📄 1. 准备 CSV 文件(如 data.csv)
alice,123456
bob,abcdef
charlie,pass123
放在 JMeter 的 bin 目录下,或使用绝对路径(如 C:/test/data.csv)。
🔧 2. 在 HTTP 请求中使用 __CSVRead()
场景:每次请求读取一行,包含用户名和密码
在 HTTP Request 的参数或 Body 中这样写:
username: ${__CSVRead(data.csv,0)}
password: ${__CSVRead(data.csv,1)}
${__CSVRead(data.csv,next)}
🔑 关键点:
- 先读第 0 列(用户名)
- 再读第 1 列(密码)
- 最后用
${__CSVRead(data.csv,next)}移动到下一行
🔄 3. 循环读取(实现循环)
__CSVRead() 默认不会循环!当读到文件末尾时会返回空值。
✅ 解决方案:配合 用户定义的变量 + 函数嵌套 或 改用 CSV Data Set Config
但如果你坚持用 __CSVRead() 实现循环,可以这样做:
方法:使用 __counter() + __V() + 预先知道行数
❌ 不推荐!太复杂且不健壮。
✅ 更佳建议:
除非有特殊需求(如跳行、随机读),否则优先使用
CSV Data Set Config,它原生支持循环(Recycle on EOF = True)。
✅ 三、__CSVRead() 的典型使用场景
| 场景 | 说明 |
|---|---|
| 同一行多次引用 | 先读所有列,再用 ${__CSVRead(file,next)} 换行 |
| 非顺序读取 | 可以先读第2列,再读第0列 |
| 多文件交叉读取 | 同时读 user.csv 和 product.csv |
✅ 四、完整示例(线程组配置)
假设你有一个线程,要发 3 次请求,分别用 CSV 的 3 行数据:
- 线程组 → Loop Count = 3
- HTTP Request 参数如下:
| Name | Value |
|---|---|
| user | ${__CSVRead(data.csv,0)} |
| pwd | ${__CSVRead(data.csv,1)} |
- 在 HTTP Request 最后添加一个“虚拟”参数(或用 User Defined Variables)来触发换行:
next_line=${__CSVRead(data.csv,next)}
💡 技巧:也可以在 Sampler 名称 或 注释 中写
${__CSVRead(data.csv,next)},只要它被解析就行。
⚠️ 五、注意事项
- 路径问题:建议用绝对路径,避免找不到文件。
${__CSVRead(C:/jmeter/data.csv,0)} - 编码问题:
__CSVRead()不支持指定编码!如果 CSV 含中文,确保文件是 ANSI 或系统默认编码(Windows 通常是 GBK)。
👉 含中文时强烈建议用CSV Data Set Config(可设 UTF-8) - 性能:
__CSVRead()每次调用都读文件,性能低于CSV Data Set Config(后者缓存到内存)。 - 线程安全:多个线程共用一个
__CSVRead(file,*)会导致读取错乱!此时应为每个线程用不同文件或改用CSV Data Set Config+Sharing mode = Current thread。
✅ 六、对比:__CSVRead() vs CSV Data Set Config
| 特性 | __CSVRead() |
CSV Data Set Config |
|---|---|---|
| 支持循环 | ❌(需手动处理) | ✅(Recycle on EOF) |
| 支持 UTF-8 | ❌ | ✅ |
| 性能 | 较低(每次读磁盘) | 高(加载到内存) |
| 灵活性 | 高(可跳列、跳行) | 低(顺序读) |
| 多线程安全 | ❌(需小心) | ✅(可配置共享模式) |
| 推荐使用 | 特殊场景 | 绝大多数场景 |
✅ 结论
- 一般情况 → 用
CSV Data Set Config(简单、高效、支持循环和 UTF-8) - 特殊需求(如动态跳行、多列交叉)→ 用
__CSVRead()
如果你只是想“循环读取 CSV”,请优先使用 CSV Data Set Config 并设置 Recycle on EOF = True,这是最稳妥的方式。
需要我帮你写一个完整的 __CSVRead() 示例脚本吗?
配合 用户定义的变量 + 函数嵌套 ,帮忙写一个读取csv的案例
当然可以!下面是一个 使用 JMeter 的 __CSVRead() 函数 + 用户定义的变量 + 函数嵌套 来实现 循环读取 CSV 文件 的完整案例。
⚠️ 注意:由于
__CSVRead()本身不支持自动循环,我们将通过 预加载所有行到用户变量 的方式模拟“循环”(适用于数据量不大的场景)。
🎯 目标
- 读取
users.csv(3 行) - 在 HTTP 请求中循环使用这 3 行数据(第4次请求回到第1行)
- 使用 用户定义的变量 +
__V()+__counter()实现动态列值引用
📄 1. 准备 CSV 文件
users.csv(放在 JMeter 的 bin 目录下):
alice,123456
bob,abcdef
charlie,pass123
🔧 2. 测试计划结构
Test Plan
└── Thread Group (Loop Count = 5)
├── User Defined Variables
│ └── 预加载 CSV 所有行(关键!)
└── HTTP Request
└── 使用动态变量 ${username}, ${password}
✅ 3. 配置 User Defined Variables(预加载数据)
右键线程组 → Add > Config Element > User Defined Variables
在表格中手动添加如下变量(按行预加载):
| Name | Value |
|---|---|
| user_0 | ${__CSVRead(users.csv,0)} |
| pwd_0 | ${__CSVRead(users.csv,1)} |
| dummy_0 | ${__CSVRead(users.csv,next)} |
| user_1 | ${__CSVRead(users.csv,0)} |
| pwd_1 | ${__CSVRead(users.csv,1)} |
| dummy_1 | ${__CSVRead(users.csv,next)} |
| user_2 | ${__CSVRead(users.csv,0)} |
| pwd_2 | ${__CSVRead(users.csv,1)} |
| dummy_2 | ${__CSVRead(users.csv,next)} |
💡 说明:
- 我们提前把 CSV 的每一行读出来,存为
user_0,user_1,user_2...dummy_x是为了触发next换行(必须)- 这样 CSV 文件只在测试启动时读一次,后续直接用变量
✅ 此时 JMeter 启动时会自动执行这些函数,将 CSV 内容加载到内存变量中。
✅ 4. 在 HTTP Request 中动态引用(实现循环)
现在我们要根据当前循环次数(从 0 开始)动态选择 user_0、user_1 或 user_2。
步骤:
-
添加一个 Counter(可选,也可用内置变量)
- 右键线程组 → Add > Logic Controller > Counter
- 配置:
- Start:
0 - Increment:
1 - Maximum:
2(因为索引是 0,1,2) - Reference Name:
idx
- Start:
这样每次循环
idx会变成 0 → 1 → 2 → 0 → 1... -
或者更简单:直接用
${__counter(0,)}获取从 0 开始的计数器
在 HTTP Request 中使用:
方法一:使用 __counter + __V(推荐,无需额外元件)
在 HTTP Request 的参数或 Body 中写:
username: ${__V(user_${__counter(0,)})}
password: ${__V(pwd_${__counter(0,)})}
🔍 解释:
${__counter(0,)}返回 0,1,2,3,4...- 但我们只有 3 行(索引 0~2),所以需要 取模!
✅ 改进:加入取模实现真正循环(0→1→2→0→1...)
JMeter 没有直接取模函数,但可以用 BeanShell 或 JSR223,但这里我们用一个技巧:
假设你知道总行数(比如 3 行),可以这样:
${__V(user_${__intSum(${__counter(0,)},0,)})}
❌ 不行,还是无法取模。
✅ 最佳方案:用 JSR223 PreProcessor + Groovy 计算索引(简洁可靠)
- 在 HTTP Request 前添加 JSR223 PreProcessor
- 语言选择 groovy
- 脚本内容:
// 总行数(必须和 CSV 行数一致)
int totalRows = 3
// 获取全局计数器(从0开始)
long count = vars.getObject("globalCounter") as Long ?: 0L
// 计算当前索引(循环)
int index = (int)(count % totalRows)
// 保存到变量
vars.put("current_index", index.toString())
// 更新计数器
vars.putObject("globalCounter", count + 1)
- 然后在 HTTP Request 中使用:
username: ${__V(user_${current_index})}
password: ${__V(pwd_${current_index})}
✅ 最终效果(Loop Count = 5)
| 循环次数 | current_index | username | password |
|---|---|---|---|
| 1 | 0 | alice | 123456 |
| 2 | 1 | bob | abcdef |
| 3 | 2 | charlie | pass123 |
| 4 | 0 | alice | 123456 |
| 5 | 1 | bob | abcdef |
✅ 完美循环!
📌 总结:为什么这样做?
__CSVRead()不能自动循环 → 预加载到变量- 用
__V()动态拼接变量名 →${__V(user_0)}=alice - 用 Groovy 计算取模 → 实现无限循环
⚠️ 注意事项
- CSV 行数必须固定,且与代码中的
totalRows一致 - 如果 CSV 很大(>1000 行),不建议预加载(内存占用高)
- 含中文? →
__CSVRead()不支持 UTF-8!建议改用 CSV Data Set Config - 此方案适合 小数据量 + 特殊控制需求
💡 更简单替代方案(强烈推荐)
如果你不需要 __CSVRead() 的灵活性,直接用 CSV Data Set Config:
- Filename:
users.csv - Variable Names:
username,password - Recycle on EOF? → True
- Stop thread on EOF? → False
一行配置搞定循环,支持 UTF-8,性能更好!
总结:
- CSV 函数 需要配合 用户定义的变量一起使用, 如果数据很多就比较麻烦
- CSV 函数 如果不配和用户订单的变量一起使用,在请求体中的访问CSV 中的数据只能写死
本文来自博客园,作者:chuangzhou,转载请注明原文链接:https://www.cnblogs.com/czzz/p/15908474.html

浙公网安备 33010602011771号