Java中字符串分割使用split(),按照.切分出错的解决办法

本文深入探讨了Java中使用split方法进行字符串分割时遇到的常见问题,特别是当分割符为特殊字符时如何正确转义,避免数组越界错误。通过实例展示了正确的字符串分割技巧。

问题产生:

今天日常做PAT的时候,有一个输入一串数据,给出的输入是按照点分割的,所以第一时间就想到了用nextLine()读取一行字符串,trim去括号后用split来分割成String字符串数组,最后在挨个转成int来存储,于是,就有了如下代码:

public class _1037_HogwartsCoin {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String[] money = sc.nextLine().trim().replace(" ", ".").split(".");
		
		for(int i=0;i<money.length;i++) {
			System.out.println(money[i]);
		}

		int knutP = Integer.parseInt(money[2]); //一块
		int sikleP= Integer.parseInt(money[1]);//29块
		int GalleonP= Integer.parseInt(money[0]);//17*29块 493
		Coin P = new Coin(knutP,sikleP,GalleonP);
		int knutA = Integer.parseInt(money[5]); //一块
		int sikleA= Integer.parseInt(money[4]);//29块
		int GalleonA= Integer.parseInt(money[3]);//17*29块 493
		Coin A = new Coin(knutA,sikleA,GalleonA);


		

	}

然后尝试输入后报错

数组越界。。。蒙了啊

解决办法:

通过万能的网络,得到一个结论:split()方法接受的是正则表达式,所以传入的”.”就变成了正则表达式的关键字,表示除换行符之外的任意字符。所以,这里需要转义”\\.”或”[.]”。

问题解决!

package com.wsnd.wsny; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.speech.tts.TextToSpeech; import android.speech.tts.UtteranceProgressListener; import android.util.Log; import android.webkit.JavascriptInterface; import android.webkit.ValueCallback; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import android.app.Activity; import android.content.res.Configuration; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.UUID; public class MainActivity extends Activity implements TextToSpeech.OnInitListener { private static final String TAG = "HighlightReader"; private WebView mWebView; private TextToSpeech tts; private boolean isSpeaking = false; private boolean isPaused = false; private int currentSentenceIndex = 0; private int currentCharIndex = 0; private String[] sentences; // 用于朗读的句子 private String fullOriginalText; // 完整原始文本 private Handler handler = new Handler(); private SharedPreferences sharedPreferences; private boolean isTTSInitialized = false; // 添加这行:TTS初始化状态标志 // JS交互接口:接收网页文本节点信息 public class TextNodeInterface { @JavascriptInterface public void onTextNodesCollected(String fullText, String nodeInfo) { Log.d(TAG, "收到文本节点信息:fullText长度=" + (fullText == null ? 0 : fullText.length())); runOnUiThread(() -> { if (fullText == null || fullText.trim().isEmpty()) { Toast.makeText(MainActivity.this, "未提取到有效文本", Toast.LENGTH_SHORT).show(); return; } fullOriginalText = fullText; splitSentences(fullText); // 分割句子 }); } } // 检查TTS是否可用 private boolean isTTSReady() { return tts != null && isTTSInitialized && tts.getEngines().size() > 0; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sharedPreferences = getSharedPreferences("TTSPreferences", MODE_PRIVATE); loadProgress(); initTextToSpeech(); setupWebView(); loadWebContent("file:///android_asset/index.html"); // 替换为你的网页路径 setupButtons(); } // 初始化TTS private void initTextToSpeech() { tts = new TextToSpeech(this, this); setUtteranceProgressListener(); } // 配置WebView private void setupWebView() { mWebView = findViewById(R.id.mWebView); WebSettings settings = mWebView.getSettings(); settings.setJavaScriptEnabled(true); settings.setDomStorageEnabled(true); settings.setAllowFileAccess(true); settings.setAllowContentAccess(true); // 允许JS调用Android接口(跨域配置) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { settings.setAllowUniversalAccessFromFileURLs(true); } // 添加JS交互接口 mWebView.addJavascriptInterface(new TextNodeInterface(), "TextNodeInterface"); mWebView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); Log.d(TAG, "网页加载完成,开始收集文本节点(延迟2秒适配动态内容)"); // 延迟2秒执行,确保Vue等动态内容渲染完成 handler.postDelayed(() -> collectTextNodes(), 2000); } }); } // 从assets加载JS文件(避免Java字符串转义错误) private String loadJsFromAssets(String filename) { try { InputStream is = getAssets().open(filename); byte[] buffer = new byte[is.available()]; is.read(buffer); is.close(); return new String(buffer, "UTF-8"); } catch (IOException e) { Log.e(TAG, "加载JS文件失败:" + e.getMessage()); return ""; } } // 注入JS收集文本节点 private void collectTextNodes() { String js = loadJsFromAssets("collect_text_nodes.js"); if (js.isEmpty()) { Log.e(TAG, "JS文件内容为空,无法收集文本"); return; } mWebView.evaluateJavascript(js, new ValueCallback<String>() { @Override public void onReceiveValue(String result) { Log.d(TAG, "文本收集JS执行结果:" + result); } }); } // 分割句子(适配过滤后为空的情况) private void splitSentences(String fullText) { Log.d(TAG, "原始文本内容:" + fullText); // Step 1: 过滤特定标签和引用(保持原有逻辑) String normalRegex = ""; String tempText = fullText.replaceAll(normalRegex, ""); String specialRegex = ""; tempText = tempText.replaceAll(specialRegex, ""); String filteredText = tempText.replaceAll(specialRegex, ""); if (filteredText.trim().isEmpty()) { filteredText = fullText.trim(); } // Step 2: 使用增强型正则进行句子分割 List<String> sentenceList = new ArrayList<>(); // 先按段落拆分(利用换行、双换行作为自然分隔) String[] paragraphs = filteredText.split("\\n\\s*\\n|\\r\\n\\s*\\r\\n"); // 双换行视为段落分割 for (String para : paragraphs) { para = para.trim(); if (para.isEmpty()) continue; // 在每个段落内进一步切分为句子 List<String> sentencesInPara = splitParagraphIntoSentences(para); sentenceList.addAll(sentencesInPara); } // 转为数组并赋值 sentences = sentenceList.toArray(new String[0]); Log.d(TAG, "分割完成,句子数量:" + sentences.length); if (sentences.length == 0) { Toast.makeText(this, "未找到可朗读的句子", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "已提取" + sentences.length + "个句子", Toast.LENGTH_SHORT).show(); } } // 按句子分隔符切分段落为句子列表 private List<String> splitParagraphIntoSentences(String paragraph) { List<String> sentenceList = new ArrayList<>(); // 使用正则表达式按中文句号、英文句号、问号、感叹号分割句子 String[] parts = paragraph.split("[。.!??!]"); for (String part : parts) { if (!part.trim().isEmpty()) { sentenceList.add(part.trim()); } } return sentenceList; } // 配置按钮事件 private void setupButtons() { Button speakButton = findViewById(R.id.speakButton); speakButton.setOnClickListener(v -> { if (sentences == null || sentences.length == 0) { Toast.makeText(this, "无可朗读的内容", Toast.LENGTH_SHORT).show(); return; } if (isPaused) { isPaused = false; speakFromCurrentPosition(); Toast.makeText(this, "朗读继续", Toast.LENGTH_SHORT).show(); } else { startSpeaking(); } }); Button stopButton = findViewById(R.id.stopButton); stopButton.setOnClickListener(v -> { stopSpeaking(); Toast.makeText(this, "朗读已停止", Toast.LENGTH_SHORT).show(); }); Button pauseButton = findViewById(R.id.pauseButton); pauseButton.setOnClickListener(v -> { if (isSpeaking) { tts.stop(); isSpeaking = false; isPaused = true; Toast.makeText(this, "朗读已暂停", Toast.LENGTH_SHORT).show(); } }); } // 开始朗读 private void startSpeaking() { if (fullOriginalText == null || fullOriginalText.isEmpty()) { Toast.makeText(this, "未加载到文本", Toast.LENGTH_SHORT).show(); return; } if (!isTTSReady()) { Toast.makeText(this, "TTS服务不可用", Toast.LENGTH_SHORT).show(); return; } speakFromCurrentPosition(); } // 停止朗读 private void stopSpeaking() { tts.stop(); saveProgress(); clearHighlight(); currentSentenceIndex = 0; currentCharIndex = 0; isSpeaking = false; isPaused = false; } // 设置TTS进度监听 private void setUtteranceProgressListener() { tts.setOnUtteranceProgressListener(new UtteranceProgressListener() { @Override public void onStart(String utteranceId) { isSpeaking = true; isPaused = false; } @Override public void onDone(String utteranceId) { currentSentenceIndex++; currentCharIndex = 0; if (currentSentenceIndex < sentences.length) { handler.postDelayed(MainActivity.this::speakFromCurrentPosition, 100); } else { isSpeaking = false; runOnUiThread(() -> { clearHighlight(); Toast.makeText(MainActivity.this, "播放完成", Toast.LENGTH_SHORT).show(); }); } } @Override public void onError(String utteranceId) { isSpeaking = false; runOnUiThread(() -> Toast.makeText(MainActivity.this, "朗读出错", Toast.LENGTH_SHORT).show()); } }); } // 从当前位置开始朗读 private void speakFromCurrentPosition() { if (sentences == null || currentSentenceIndex >= sentences.length) { Log.w(TAG, "朗读结束或句子数组为空"); return; } String sentenceToSpeak = sentences[currentSentenceIndex].trim(); if (sentenceToSpeak.isEmpty()) { Log.d(TAG, "跳过空句子,索引: " + currentSentenceIndex); currentSentenceIndex++; speakFromCurrentPosition(); return; } // 查找句子在原始文本中的位置 int startInOriginal = findSentenceInOriginalText(sentenceToSpeak); if (startInOriginal == -1) { Log.e(TAG, "❌ 无法定位句子在原文中的位置: \"" + sentenceToSpeak + "\""); currentSentenceIndex++; speakFromCurrentPosition(); return; } // 计算高亮范围 int highlightStart = startInOriginal + currentCharIndex; int highlightEnd = startInOriginal + sentenceToSpeak.length(); if (highlightEnd > fullOriginalText.length()) { highlightEnd = fullOriginalText.length(); } Log.d(TAG, "计算高亮范围: start=" + highlightStart + ", end=" + highlightEnd); // 高亮并朗读 highlightInOriginalText(highlightStart, highlightEnd); String partToSpeak = sentenceToSpeak.substring(currentCharIndex); try { Bundle params = new Bundle(); String utteranceId = UUID.randomUUID().toString(); params.putCharSequence(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId); // 添加TTS状态检查 if (tts != null) { int result = tts.speak(partToSpeak, TextToSpeech.QUEUE_FLUSH, params, utteranceId); if (result == TextToSpeech.ERROR) { Log.e(TAG, "TTS朗读失败"); Toast.makeText(this, "朗读失败", Toast.LENGTH_SHORT).show(); } } else { Log.e(TAG, "TTS对象为空"); Toast.makeText(this, "TTS未初始化", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { Log.e(TAG, "TTS朗读异常: " + e.getMessage()); Toast.makeText(this, "朗读出错: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } currentCharIndex += partToSpeak.length(); } // 在原始文本中查找句子位置(简化匹配逻辑) private int findSentenceInOriginalText(String sentence) { // 移除空格后匹配(提高兼容性) String originalNoSpace = fullOriginalText.replaceAll("\\s+", ""); String sentenceNoSpace = sentence.replaceAll("\\s+", ""); int index = originalNoSpace.indexOf(sentenceNoSpace); Log.d(TAG, "查找句子位置: " + sentence + ", 位置: " + index); return index; } // 高亮原始文本中指定范围 private void highlightInOriginalText(int start, int end) { Log.d(TAG, "准备高亮文本,起始位置: " + start + ", 结束位置: " + end); if (fullOriginalText == null || start < 0 || end > fullOriginalText.length() || start >= end) { Log.e(TAG, "高亮失败:无效的范围,start=" + start + ", end=" + end + ", 文本长度=" + (fullOriginalText != null ? fullOriginalText.length() : "null")); return; } String highlightedText = fullOriginalText.substring(start, end); Log.d(TAG, "即将高亮的内容片段: \"" + highlightedText + "\""); String highlightJs = "(function(start, end) {" + " var style = document.createElement('style');" + " style.innerHTML = 'mark.highlight { background-color: yellow !important; }';" + " document.head.appendChild(style);" + " var oldMarks = document.querySelectorAll('mark.highlight');" + " oldMarks.forEach(function(mark) {" + " var parent = mark.parentNode;" + " parent.replaceChild(document.createTextNode(mark.textContent), mark);" + " parent.normalize();" + " });" + " var currentPos = 0;" + " var textNodes = [];" + " function traverse(node) {" + " if (node.nodeType === Node.TEXT_NODE) {" + " var text = node.textContent;" + " var nodeStart = currentPos;" + " var nodeEnd = currentPos + text.length;" + " textNodes.push({node: node, start: nodeStart, end: nodeEnd});" + " currentPos = nodeEnd;" + " } else if (node.nodeType === Node.ELEMENT_NODE && ['SCRIPT', 'STYLE', 'NOSCRIPT'].indexOf(node.tagName) === -1) {" + " for (var i = 0; i < node.childNodes.length; i++) {" + " traverse(node.childNodes[i]);" + " }" + " }" + " }" + " var container = document.getElementById('main') || document.body;" + " traverse(container);" + " console.log('JS端收集到的文本节点总数:', textNodes.length);" + " console.log('目标高亮区间: [' + start + ', ' + end + ')');" + " var matchFound = false;" + " textNodes.forEach(function(item) {" + " if (item.end > start && item.start < end) {" + " matchFound = true;" + " var node = item.node;" + " var text = node.textContent;" + " var hStart = Math.max(0, start - item.start);" + " var hEnd = Math.min(text.length, end - item.start);" + " var before = document.createTextNode(text.substring(0, hStart));" + " var mark = document.createElement('mark');" + " mark.className = 'highlight';" + " mark.style.backgroundColor = 'yellow';" + " mark.textContent = text.substring(hStart, hEnd);" + " console.log('【JS日志】创建mark元素,内容: \"' + mark.textContent + '\", 范围: [' + hStart + ', ' + hEnd + ']');" + " var parent = node.parentNode;" + " parent.insertBefore(before, node);" + " parent.insertBefore(mark, node);" + " parent.insertBefore(after = document.createTextNode(text.substring(hEnd)), node);" + " parent.removeChild(node);" + " }" + " });" + " if (matchFound) {" + " console.log('【JS日志】✅ 成功完成高亮');" + " } else {" + " console.warn('【JS日志】❌ 未找到匹配的文本节点进行高亮');" + " }" + " setTimeout(function() {" + " var mark = document.querySelector('mark.highlight');" + " if (mark) {" + " mark.scrollIntoView({ behavior: 'smooth', block: 'center' });" + " console.log('【JS日志】✅ 滚动到高亮位置');" + " } else {" + " console.warn('【JS日志】⚠️ 页面上没有发现 mark.highlight 元素');" + " }" + " }, 100);" + "})(" + start + ", " + end + ");"; // 注入JS后监听返回值 mWebView.evaluateJavascript(highlightJs, new ValueCallback<String>() { @Override public void onReceiveValue(String value) { Log.d(TAG, "高亮JS执行结果回调: " + value); if (value == null || value.equals("null")) { Log.d(TAG, "✅ 高亮JS已执行(无返回值是正常的)"); } else { Log.d(TAG, "JS返回值: " + value); } } }); // Java层确认调用发出 Log.d(TAG, "✅ 已发送高亮指令,范围 [" + start + ", " + end + "),内容: \"" + highlightedText + "\""); } // 清除所有高亮 private void clearHighlight() { String clearJs = "var marks = document.querySelectorAll('mark.highlight');" + "marks.forEach(function(mark) {" + " var parent = mark.parentNode;" + " parent.replaceChild(document.createTextNode(mark.textContent), mark);" + " parent.normalize();" + "});"; mWebView.evaluateJavascript(clearJs, null); } // 加载网页内容 private void loadWebContent(String url) { try { mWebView.loadUrl(url); } catch (Exception e) { Toast.makeText(this, "加载失败: " + e.getMessage(), Toast.LENGTH_SHORT).show(); Log.e(TAG, "加载失败", e); } } // 加载上次进度 private void loadProgress() { currentSentenceIndex = sharedPreferences.getInt("currentSentenceIndex", 0); currentCharIndex = sharedPreferences.getInt("currentCharIndex", 0); Log.d(TAG, "加载进度:句子=" + currentSentenceIndex + ", 字符=" + currentCharIndex); } // 保存当前进度 private void saveProgress() { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putInt("currentSentenceIndex", currentSentenceIndex); editor.putInt("currentCharIndex", currentCharIndex); editor.apply(); Log.d(TAG, "保存进度:句子=" + currentSentenceIndex + ", 字符=" + currentCharIndex); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } @Override public void onBackPressed() { if (mWebView.canGoBack()) { mWebView.goBack(); } else { super.onBackPressed(); } } @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { // 设置语言并检查支持情况 int result = tts.setLanguage(Locale.CHINESE); if (result == TextToSpeech.LANG_MISSING_DATA) { Toast.makeText(this, "缺少TTS数据", Toast.LENGTH_SHORT).show(); Log.e(TAG, "TTS缺少语言数据"); isTTSInitialized = false; } else if (result == TextToSpeech.LANG_NOT_SUPPORTED) { Toast.makeText(this, "不支持中文朗读", Toast.LENGTH_SHORT).show(); Log.e(TAG, "TTS不支持中文语言"); isTTSInitialized = false; } else { Log.d(TAG, "TTS初始化成功(支持中文)"); isTTSInitialized = true; // 设置初始化成功标志 } } else { Toast.makeText(this, "TTS初始化失败", Toast.LENGTH_SHORT).show(); Log.e(TAG, "TTS初始化失败,状态码=" + status); isTTSInitialized = false; } } @Override protected void onDestroy() { if (tts != null) { tts.stop(); tts.shutdown(); } super.onDestroy(); } } 你看下这段代码,认真解释下。
最新发布
10-13
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值