ページ 11

【解決済み】jsにおけるバイト数でShift_JIS文字列を分割する方法

Posted: 2022年2月24日(木) 09:58
by ドラムカン
いつもお世話になっております。

JavaScriptにおきまして、
Shift_JISの文字列をバイト数でカウントするには
以下のコードで可能ですが、バイト数で文字列を分割する方法が不明です。

コード: 全て選択

String.prototype.bytes = function () {
  var length = 0;
  for (var i = 0; i < this.length; i++) {
    var c = this.charCodeAt(i);
    if ((c >= 0x0 && c < 0x81) || (c === 0xf8f0) || (c >= 0xff61 && c < 0xffa0) || (c >= 0xf8f1 && c < 0xf8f4)) {
      length += 1;
    } else {
      length += 2;
    }
  }
  return length;
};
jsにおける文字列の分割は、
substr/substring/splitメソッドが主ですが
これらは、文字数による分割ですので
バイト数での分割というメソッドが見当たりませんでした。

何をしたいのかと申しますと
バトルメッセージを指定の位置で改行して表示したいと考えており、
それを実現するためには、
1バイト文字と2バイト文字を加味した位置で改行コードを入れる必要があります。
(※メッセージログを取るプラグインとの兼ね合いで、ログの方は改行不要のため
  このような邪道なやり方を試みております)

詳細を申し上げますと、
上記のコードを用い、
if(text.bytes() > 50){
とすることで、バイト数での分岐はできますものの
textに入った文字列を、変数「textA」と「textB」に分割したいと考えておりますが
バイト数で分割できないといった状況です。

jsにお詳しい方がいらっしゃいましたら
何とぞご教示いただけますと幸いです。
どうかよろしくお願いいたします。

Re: jsにおけるバイト数でShift_JIS文字列を分割する方法

Posted: 2022年2月25日(金) 01:37
by WTR
バイトカウントと同時に
シングルバイト文字とダブルバイト文字それぞれの文字数カウントを行えば
文字数換算の区切り位置を決められそうです

例示されている bytes() をちょっと弄っただけですが
バイト区切り位置を引数で与えると文字数換算の区切り位置を返す…

コード: 全て選択

String.prototype.bytePos = function (bytePos) {
	let bytes = 0;
	let singleByteChar = 0;
	let doubleByteChar = 0;
	for (let i = 0; i < this.length; i++) {
		let c = this.charCodeAt(i);
		if ((c >= 0x0 && c < 0x81) || (c === 0xf8f0) || (c >= 0xff61 && c < 0xffa0) || (c >= 0xf8f1 && c < 0xf8f4)) {
			singleByteChar += 1;
			bytes += 1;
		} else {
			doubleByteChar += 1;
			bytes += 2;
		}

		// ------ RoundUp ------ //
//		if (bytes >= bytePos) {
//			return singleByteChar + doubleByteChar;
//		}

		// ------ RoundDown ------ //
		if (bytes > bytePos) {
			return singleByteChar + doubleByteChar - 1;
		}
		if (bytes === bytePos) {
			return singleByteChar + doubleByteChar;
		}
	}
};

コード: 全て選択

"abcあいde".bytePos(1) // 1 --> a
"abcあいde".bytePos(2) // 2 --> ab
"abcあいde".bytePos(3) // 3 --> abc
"abcあいde".bytePos(4) // 3 --> abc
"abcあいde".bytePos(5) // 4 --> abcあ
"abcあいde".bytePos(6) // 4 --> abcあ
"abcあいde".bytePos(7) // 5 --> abcあい
"abcあいde".bytePos(8) // 6 --> abcあいd
"abcあいde".bytePos(9) // 7 --> abcあいde
"abcあいde" 7文字 9バイトを 4バイト + 5バイトに分けることはできないので
4バイトで区切ろうとした場合は 3 を返すようにしています。切り下げ的な考え。

Re: jsにおけるバイト数でShift_JIS文字列を分割する方法

Posted: 2022年2月25日(金) 02:11
by ドラムカン
WTR 様

いつも大変お世話になっております。
なるほど! Roundがありましたか。
素晴らしい考え方ですね。
毎度のことながら120%のご回答をくださり、本当にありがとうございます。

ひとつお伺いしたいのですが、
"abcあいde"を、"abcあ"と"いde"に分けたいとき、
どのようになるでしょうか?

度々、ご質問してしまって申し訳ございません。

Re: jsにおけるバイト数でShift_JIS文字列を分割する方法

Posted: 2022年2月25日(金) 09:21
by WTR
ドラムカン さんが書きました:jsにおける文字列の分割は、
substr/substring/splitメソッドが主ですが
これらは、文字数による分割ですので
文字数がわかれば分割する方法はわかるということかと思ったので
バイト --> 文字数換算 の方法を考えてみた次第でしたが。

↾ の bytePos を使い5バイトの位置(4文字目)で分割するなら

コード: 全て選択

const text = "abcあいde";
const textA = text.substring(0, text.bytePos(5));
const textB = text.substring(text.bytePos(5));
とかですかね。もっといい方法があったかもしれないですが。

Re: jsにおけるバイト数でShift_JIS文字列を分割する方法

Posted: 2022年2月25日(金) 10:13
by ドラムカン
WTR様

丁寧にご返答くださり、本当にありがとうございます。

すみません。
substr/substring/splitメソッドは文字数しか区切れないという固定観念があり
せっかくWTR様が明示してくださった文字数との相関例から、推し量ることができませんでした。
つくづく自分の無能さに嫌気がさします。
余計なお手間を取らせてしまい、誠に申し訳ございません。

このような者に
いつもご親切にしてくださり、深く感謝申し上げます。
今回も他力本願に甘んじてしましたが、
こうして答えをいただけること自体、普通ではなく、大変ありがたいことだと感じております。

今後とも、どうかよろしくお願いいたします。