reset的失效问题

 

在 DOM 中,表单重置非常简单,使用 <input type=”reset”> 或者 <button type=”reset”> 即可。原生 DOM 也提供了 reset() 方法用于表单重置。

但是在 Firefox/Chrome 浏览器中,如果字段是隐藏域(type=”hidden”)的话,使用 reset 是无法将字段值还原为初始值的。但在 IE6/7/8 中都可以重置。

目前得到的解决方案是

<input type="text" name="aa" style="display:none;">
下面我给出一个完整的测试例子,我在ie和标准浏览器等数十种浏览器下面没有发现任何问题,有需要的同学们可以参考
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<script>
function inputValue(){
	document.getElementById("aa").value="123456";
}
function showValue(){
	alert(document.getElementById("aa").value);
	}
</script>
<style>
#aa{
	display:none;
	}
</style>
</head>

<body>
<form id="form1" name="form1" method="post" action="">
  <input type="text" name="textfield" id="textfield" />
  <input type="text" name="textfield2" id="textfield2" />
  <input type="text" name="textfield2" value="nnn" id="aa" />
  <input type="button" onclick="inputValue()" value="value" />
  <input type="submit" name="button" id="button" value="提交" />
  <input type="reset" name="button2" id="button2" value="重置" />
</form>
<a href="javascript:showValue()">show value</a>
</body>
</html>

<think>我们正在讨论Java IO流中的`mark()`和`reset()`方法,以及如何利用它们实现重复读取操作。根据引用内容,这两个方法主要用于在输入流中标记一个位置,之后可以通过`reset()`方法回到该位置重新读取数据。这在某些需要“回看”的场景中非常有用。 ### 核心概念 1. **`mark(int readlimit)`方法**:在输入流的当前位置设置一个标记。参数`readlimit`表示在标记失效前可以读取的最大字节数(或字符数)。如果读取的字节数超过了这个限制,标记可能会失效(但根据引用[1][4],在使用缓冲流时,即使超出限制,标记有时仍然有效)。 2. **`reset()`方法**:将流重置到最后一次调用`mark()`方法时的位置,允许重新读取从标记位置到当前重置位置之间的数据。 3. **支持情况**:不是所有的流都支持`mark()`和`reset()`。例如,`FileInputStream`默认不支持,而`BufferedInputStream`支持(引用[2])。我们可以通过`markSupported()`方法检查流是否支持标记操作。 ### 使用场景 - 需要重复读取一段数据(例如,解析不确定长度的数据时,先读取一部分进行判断,如果不符合条件则回退重新读取)。 - 替换文件中的特定字符串(引用[3]):标记当前位置,读取一段数据,检查是否包含目标字符串,若包含则替换并写入,否则重置到标记位置继续读取。 ### 实现步骤 1. **创建支持mark/reset的输入流**:通常使用缓冲流(如`BufferedInputStream`或`BufferedReader`)包装基础流。 2. **检查是否支持mark/reset**:调用`markSupported()`确认。 3. **设置标记**:在需要的位置调用`mark(readlimit)`,设置一个标记,并指定读取限制。 4. **读取数据**:读取一定量的数据(不超过`readlimit`,但缓冲流可能允许超出)。 5. **判断是否需要重置**:如果读取的数据不满足条件,调用`reset()`回到标记位置,然后尝试其他处理;如果满足条件,则继续读取。 6. **重置后重新读取**:从标记位置开始重新读取数据。 ### 示例代码:使用BufferedReader重复读取 以下示例展示如何使用`BufferedReader`的`mark()`和`reset()`方法重复读取一段文本: ```java import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class MarkResetExample { public static void main(String[] args) { try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"))) { // 检查是否支持mark/reset if (!reader.markSupported()) { System.out.println("mark/reset not supported"); return; } // 读取第一行并标记 String line = reader.readLine(); System.out.println("Line 1: " + line); // 设置标记,参数readlimit设为100(表示我们期望在重置前最多读取100个字符) reader.mark(100); // 读取第二行 line = reader.readLine(); System.out.println("Line 2: " + line); // 重置到标记位置(即第二行开始处) reader.reset(); // 重新读取第二行 line = reader.readLine(); System.out.println("Line 2 again: " + line); // 继续读取第三行 line = reader.readLine(); System.out.println("Line 3: " + line); } catch (IOException e) { e.printStackTrace(); } } } ``` ### 注意事项 1. **`readlimit`参数**:它表示在标记失效前可以读取的字符数(或字节数)的上限。但实际中,如果使用缓冲流,即使读取超过这个限制,标记可能仍然有效(引用[1][4])。这是因为缓冲流内部已经将数据读入缓冲区,所以重置时可以从缓冲区获取数据。但为了安全起见,应尽量保守设置该值。 2. **标记位置**:调用`mark()`时,标记的是当前读取位置。之后读取的数据超过`readlimit`后,标记可能失效(此时调用`reset()`会抛出`IOException`)。 3. **流类型**:只有支持标记的流才能使用。例如: - 字节流:`BufferedInputStream`、`ByteArrayInputStream`支持。 - 字符流:`BufferedReader`、`CharArrayReader`支持。 - 而`FileInputStream`、`FileReader`等默认不支持,需要包装成缓冲流。 4. **重置次数**:只能重置到最后一次设置标记的位置,不能多次重置到不同的标记(除非再次调用`mark()`设置新标记)。 5. **资源管理**:使用`try-with-resources`确保流正确关闭。 ### 应用案例:替换文件中的字符串 引用[3]提到,可以使用`mark()`和`reset()`实现替换文件中的字符串。基本思路如下: 1. 使用`BufferedReader`读取文件,使用`BufferedWriter`写入新文件。 2. 在读取过程中,对每个可能匹配目标字符串的位置设置标记。 3. 读取一段数据(长度至少为目标字符串长度),检查是否包含目标字符串。 4. 如果包含,则重置到标记位置,然后写入替换字符串,并跳过目标字符串的长度。 5. 如果不包含,则重置到标记位置,写入当前读取的一个字符(或一小段),然后向前移动一个位置,重新设置标记。 由于实现较为复杂,且涉及边界处理,这里不展开详细代码。但核心思想就是利用`mark()`和`reset()`来回退重新读取。 ### 常见错误 - **`java.io.IOException: mark/reset not supported`**:在不支持标记的流上调用`mark()`或`reset()`(引用[2])。解决方法:使用支持标记的流(如缓冲流)包装。 - **标记失效**:读取超过`readlimit`后调用`reset()`导致标记失效。解决方法:确保读取的数据量在限制内,或使用足够大的缓冲区(如设置较大的`readlimit`)。 ### 总结 - `mark()`和`reset()`方法为Java IO提供了重复读取的能力,特别适合需要“回退”的场景。 - 使用缓冲流(如`BufferedInputStream`、`BufferedReader`)可以更可靠地支持这些操作。 - 合理设置`readlimit`参数,并注意标记的有效范围。 §§相关问题§§ 1. 如何在Java中实现文件内容的字符串替换? 2. 如何判断一个IO流是否支持mark和reset操作? 3. 使用mark/reset时有哪些常见陷阱? 4. 除了mark/reset,还有哪些方法可以实现流的重复读取?</think>### Java IO流中`mark()`与`reset()`方法的使用及重复操作实现 在Java IO流中,`mark()`和`reset()`方法提供了"标记-重置"机制,允许开发者在流中设置标记点并随时回退到该位置,从而实现流的重复读取操作。以下是关键知识点和实现方法: #### 一、核心概念解析 1. **`mark(int readlimit)`方法** - 在当前流位置设置标记点 - 参数`readlimit`:指定在标记失效前最多可读取的字节数 - 示例:`inputStream.mark(1024);` // 标记当前位置,允许后续读取1024字节 2. **`reset()`方法** - 将流重置到最后一次调用`mark()`时的位置 - 示例:`inputStream.reset();` // 回退到标记位置 3. **支持检测** 使用`markSupported()`检查流是否支持标记操作: ```java if (inputStream.markSupported()) { // 支持mark/reset操作 } ``` #### 二、实现重复操作的步骤 1. **创建支持mark/reset的流** 使用缓冲流包装基础流(如`BufferedInputStream`): ```java InputStream baseStream = new FileInputStream("data.txt"); InputStream inputStream = new BufferedInputStream(baseStream); // 支持mark/reset[^2] ``` 2. **设置标记点** 在需要重复读取的起始位置设置标记: ```java inputStream.mark(1024); // 标记当前位置,允许后续读取1024字节[^1] ``` 3. **读取数据并处理** ```java byte[] buffer = new byte[256]; int bytesRead = inputStream.read(buffer); // 处理数据... ``` 4. **重置流位置** 当需要重新处理数据时回退到标记点: ```java inputStream.reset(); // 回到mark()设置的位置[^3] ``` 5. **重复读取操作** ```java bytesRead = inputStream.read(buffer); // 重新读取相同数据 ``` #### 三、完整示例:替换文件中的字符串 ```java import java.io.*; public class StringReplacer { public static void main(String[] args) throws IOException { try (BufferedInputStream in = new BufferedInputStream(new FileInputStream("source.txt")); FileOutputStream out = new FileOutputStream("output.txt")) { if (!in.markSupported()) { throw new IOException("mark/reset not supported"); } byte[] target = "old".getBytes(); // 要替换的字符串 int matchIndex = 0; while (in.available() > 0) { in.mark(target.length); // 标记当前位置[^3] // 尝试匹配目标字符串 matchIndex = 0; while (matchIndex < target.length) { int nextByte = in.read(); if (nextByte == target[matchIndex]) { matchIndex++; } else { in.reset(); // 重置到标记位置 out.write(in.read()); // 写入不匹配的字节 break; } } // 完全匹配时执行替换 if (matchIndex == target.length) { out.write("new".getBytes()); // 写入替换内容 } } } } } ``` #### 四、关键注意事项 1. **缓冲流是必需的** - 基础流如`FileInputStream`不支持`mark/reset`,必须用`BufferedInputStream`包装[^2] - 推荐缓冲区大小 ≥ `readlimit`参数值 2. **`readlimit`参数的特殊性** - 实际可读取量可能超过`readlimit`(缓冲流会扩展能力)[^1][^4] - 但超出声明值可能导致未定义行为,应保守设置 3. **典型应用场景** - 模式匹配(如字符串替换) - 数据格式验证 - 回溯解析(如不确定长度的数据块处理) 4. **错误处理** 捕获可能的`IOException`: ```java try { inputStream.reset(); } catch (IOException e) { System.err.println("重置失败: " + e.getMessage()); } ``` #### 五、不同流类型的支持情况 | 流类型 | markSupported() | 说明 | |--------|----------------|------| | `FileInputStream` | ❌ | 需用`BufferedInputStream`包装 | | `BufferedInputStream` | ✅ | 最佳实践选择[^2][^4] | | `ByteArrayInputStream` | ✅ | 内存流支持 | | `CharArrayReader` | ✅ | 字符流支持[^5] | > **提示**:文本处理推荐使用`BufferedReader`+`mark()`/`reset()`,字符编码处理更安全[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值