Elixirでのバイナリパターンマッチと具体例の紹介

目次

Elixirにおけるバイナリの基本概念と特徴についての解説

Elixirにおけるバイナリは、バイトのシーケンスとして構成されており、各バイトが8ビットで表現されるデータ構造です。
このバイナリは、効率的なデータ操作や通信を可能にするため、Elixirの主要な特徴の一つとされています。
特に、文字列も内部的にはUTF-8エンコードされたバイナリとして扱われる点がユニークです。
これにより、文字列操作が簡素化され、処理の一貫性が保たれます。
さらに、Elixirではバイナリパターンマッチを活用することで、特定の形式に基づいたデータ分割や操作が可能になります。
たとえば、プロトコルの解析やバイナリデータの分解など、高度なデータ処理に対応できます。
また、`<<>>`記法によるバイナリ作成や、さまざまな操作関数の活用により、直感的かつ効率的なコーディングが実現します。
これらの特性は、Elixirの優れた並行処理能力とも相まって、高パフォーマンスなアプリケーション開発を可能にしています。

バイナリとは何か:Elixirにおける基本的な定義

Elixirにおけるバイナリは、バイトの連続データを保持するデータ型です。
`<<>>`記法を使って、明示的に定義することができます。
たとえば、`<<1, 2, 3>>`と書けば3バイトのバイナリが生成されます。
バイナリは8ビットで構成され、固定サイズのデータを効率的に表現できるため、ネットワーク通信やファイル処理など、効率性が求められる場面で重宝されます。

バイトとビットの関係性:Elixirでの扱い方

Elixirでは、1バイトを8ビットとして扱います。
たとえば、`<<255>>`は最大値である8ビットすべてが1のバイナリを示します。
ビット単位の操作も可能で、プロトコル解析や低レベルデータ処理に適しています。
Elixirの柔軟なパターンマッチ機能を活用すれば、ビット単位のデータ操作も簡単に実現できます。

バイナリの特性:効率性と用途

バイナリは、データを効率的に格納し操作するために設計されています。
たとえば、ネットワーク通信で使用されるバイトストリームの送受信や、ファイルのバイナリ形式での保存と読み込みが挙げられます。
Elixirのバイナリは、メモリ効率が高く、速度面でも優れています。

Elixirでのバイナリの具体的な用途と応用

Elixirのバイナリは幅広い分野で応用されています。
たとえば、文字列の操作、画像データの処理、さらにはプロトコルの実装などがあります。
これらの用途において、バイナリは重要な役割を果たし、Elixirの開発効率を大いに向上させます。

バイナリの使用がもたらすElixirの利便性

バイナリを使用することで、Elixirアプリケーションのデータ処理能力が飛躍的に向上します。
また、簡潔な記法と豊富な操作関数により、コーディングの手間を大幅に削減できます。
これにより、効率的で保守性の高いコードを書くことが可能になります。

Elixirでのバイナリ作成と操作方法の基本

Elixirでバイナリを作成する際は、`<<>>`記法を使用します。
この記法は直感的かつ簡潔で、開発者がバイトのシーケンスを直接指定できます。
たとえば、`<<1, 2, 3>>`と記述することで、3つのバイトからなるバイナリを生成できます。
また、Elixirにはバイナリを操作するための関数が豊富に用意されており、データの分割や結合、バイナリサイズの取得などが容易に行えます。
バイナリ操作では、パフォーマンスが重要な要素となります。
Elixirでは、バイナリは効率的にメモリを使用するよう設計されており、大量データを扱うアプリケーションでも安定した動作が期待できます。
また、ビット単位でのデータ操作も可能で、プロトコル解析や画像処理などの高度な用途にも対応できます。
この柔軟性により、Elixirのバイナリ操作は多くの開発者に支持されています。

Elixirにおけるバイナリ作成の基本構文の解説

Elixirでは、`<<>>`記法を使うことで簡単にバイナリを作成できます。
各バイトをカンマ区切りで記述し、数値で表します。
たとえば、`<<72, 101, 108, 108, 111>>`は、「Hello」という文字列をバイナリで表現したものです。
作成したバイナリはパターンマッチや他の関数で操作できます。

バイナリを操作するための主要な関数

Elixirにはバイナリ操作のための便利な関数が揃っています。
`byte_size/1`はバイナリのバイト数を取得し、`<>`演算子を使えばバイナリの結合が可能です。
また、特定のバイトを抽出したり、バイナリを分割するための関数も豊富です。

バイナリ操作における注意点とベストプラクティス

バイナリ操作時には、データのエンコード形式やサイズに注意する必要があります。
たとえば、UTF-8エンコードされた文字列を扱う場合、エンコードエラーを避けるための検証が重要です。
`String.valid?/1`を使用すると、安全性を確保できます。

複雑なバイナリデータの操作事例

複雑なバイナリデータを操作する際は、パターンマッチが非常に有効です。
たとえば、`<>`のように記述すれば、ヘッダーと本体を分離できます。
これにより、バイナリデータの解析が簡単に行えます。

Elixirのバイナリ操作が適しているユースケース

Elixirのバイナリ操作は、ネットワークプロトコルの解析や、画像や音声データの処理に適しています。
また、ファイルフォーマットの変換やログの解析といった用途でも、高いパフォーマンスを発揮します。

Elixirにおけるバイナリと文字列の関係性の詳細

Elixirでは文字列はUTF-8エンコードされたバイナリとして内部的に扱われます。
この特徴により、文字列とバイナリの間でシームレスに操作が可能です。
たとえば、`<<104, 101, 108, 108, 111>>`のようなバイナリは、`”hello”`という文字列として変換できます。
これにより、文字列操作における柔軟性と効率性が向上します。
文字列とバイナリを明確に区別するために、Elixirは関数を提供しています。
たとえば、`String.valid?/1`でバイナリが有効なUTF-8文字列かどうかを検証できます。
また、文字列からバイナリへの変換やその逆も簡単に行えます。
これにより、データの整合性を保ちながら操作が可能です。

UTF-8エンコードに基づく文字列とバイナリの関係

Elixirの文字列はUTF-8でエンコードされており、バイナリとして扱われます。
このため、文字列操作はバイナリ操作と密接に関連しています。
たとえば、`”A”`は`<<65>>`という1バイトのバイナリに変換可能です。

Elixirで文字列をバイナリとして扱う際の注意点

文字列をバイナリとして扱う場合、UTF-8エンコードが正しく行われている必要があります。
エンコードエラーを回避するため、`String.valid?/1`を使用することが推奨されます。
また、文字列の長さとバイナリサイズが一致しない場合があるため、適切に確認する必要があります。

文字列とバイナリの変換方法とその重要性

文字列をバイナリに変換するには、`String.to_charlist/1`関数が使用されます。
逆に、バイナリから文字列への変換は、`String.from_charlist/1`を利用します。
これらの操作により、データ形式の整合性を保ちながら柔軟な処理が可能です。

文字列データのエンコードとデコードの具体例

文字列データをバイナリ形式に変換し、逆にデコードするには、以下の手順を利用します。
`<<72, 101, 108, 108, 111>>`をデコードすれば、UTF-8文字列`”Hello”`として取得できます。
これは通信プロトコルやファイル処理でよく使われます。

Elixirでの文字列とバイナリの違いを理解する利点

文字列とバイナリを明確に理解することで、データ処理の効率が向上します。
たとえば、文字列操作が必要な場面では、エンコード形式を意識することでバグを減らせます。
これにより、アプリケーションの信頼性が高まります。

バイナリのサイズ確認と文字数確認の具体的な方法

Elixirでは、バイナリのサイズ(バイト数)と文字数(文字列としての長さ)を確認するための関数が提供されています。
`byte_size/1`はバイナリのバイト数を返し、`String.length/1`は文字列の文字数を返します。
これらはそれぞれ異なる情報を提供し、適切に使い分けることでデータ処理の正確性を保つことができます。
たとえば、UTF-8エンコードされた文字列では、文字数とバイト数が異なる場合があります。
「こんにちは」という文字列は、UTF-8では15バイトですが、文字数は5です。
このようなケースでは、適切な関数を使って正確な情報を取得することが重要です。
さらに、バイナリデータを扱う際には、データの正確性を保つためにバイト数を確認する必要があります。
これにより、不正なデータ操作やエラーを防ぐことができます。

byte_size関数でバイトサイズを確認する方法

`byte_size/1`関数は、バイナリのバイト数を取得するために使用されます。
たとえば、`<<104, 101, 108, 108, 111>>`というバイナリを渡すと、結果は5になります。
この関数は文字列のバイト数も取得可能です。
UTF-8エンコードされた文字列では、マルチバイト文字に注意が必要です。

String.length関数で文字数を確認する方法

`String.length/1`関数は、文字列の文字数を返します。
この関数は、UTF-8エンコードされた文字列を対象にしています。
たとえば、「こんにちは」は文字数としては5を返しますが、`byte_size/1`では15バイトとなります。
文字列データを操作する際に非常に便利です。

バイトサイズと文字数の違いが重要な理由

バイトサイズと文字数の違いを理解することは、データの正確な処理に不可欠です。
特に、ネットワーク通信やストレージ処理ではバイトサイズが重要です。
一方、文字列操作においては、文字数が重要になる場面が多いです。

具体的なコード例で確認するサイズと文字数

以下はコード例です:

string = "こんにちは"  
IO.puts byte_size(string) # 結果: 15  
IO.puts String.length(string) # 結果: 5  

この例は、バイトサイズと文字数が異なることを示しています。

サイズ確認の活用例:エラー処理や検証での利用

サイズ確認は、バイナリデータが期待通りかどうかを検証するために役立ちます。
たとえば、固定サイズのデータを扱う際、`byte_size/1`を使用して不正なデータを排除することが可能です。
また、エラーハンドリングやデータ検証においても重要な役割を果たします。

Elixirにおけるバイナリ連結と操作の実践的な方法

Elixirでは、バイナリを効率的に連結するために`<>`演算子が用意されています。
この演算子を使うことで、バイナリ同士を簡単に結合できます。
たとえば、`<<72, 101>> <> <<108, 108, 111>>`は`<<72, 101, 108, 108, 111>>`となります。
このような簡潔な記法により、複雑な操作も容易に実現できます。
また、Elixirはバイナリ操作を効率的に行えるように設計されています。
バイナリの分割、特定部分の抽出、さらにバイナリ同士の比較も簡単に行えます。
これにより、ネットワーク通信やファイル処理など、多くの場面で高いパフォーマンスを発揮します。
特に、大規模なデータセットを扱う際には、これらの機能が大いに役立ちます。

<>演算子を使ったバイナリの連結方法

`<>`演算子を使用することで、2つ以上のバイナリを連結できます。
たとえば、`<<72, 101>> <> <<108, 108, 111>>`は、結合後に`<<72, 101, 108, 108, 111>>`となります。
この操作は軽量で、パフォーマンスに優れています。

複数のバイナリを効率的に操作するテクニック

複数のバイナリを操作する際は、`Enum`モジュールを併用することが効果的です。
たとえば、複数のバイナリをマップして加工したり、結合したりする場合、`Enum.reduce/2`を使用することで効率化できます。

バイナリ連結におけるパフォーマンスの注意点

連結操作は一般的に効率的ですが、非常に大きなバイナリを扱う場合は、メモリ使用量に注意が必要です。
Elixirでは、イミュータブルなデータ構造が使用されるため、大規模な連結操作ではメモリ消費が増加します。

連結後のバイナリの確認方法とその意義

連結後のバイナリが期待通りかどうかを検証するには、`byte_size/1`やパターンマッチを活用することができます。
これにより、不整合を早期に発見し、データ処理の信頼性を向上させることが可能です。

バイナリ連結を活用した実践的なコード例

以下はコード例です:

part1 = <<72, 101>>  
part2 = <<108, 108, 111>>  
combined = part1 <> part2  
IO.inspect combined # 結果: <<72, 101, 108, 108, 111>>  

このようなシンプルな操作で、効率的にバイナリを連結できます。

Elixirでのバイナリパターンマッチと具体例の紹介

Elixirでは、バイナリパターンマッチングを使用して効率的にバイナリデータを操作できます。
この機能は、バイナリデータを解析したり、特定の部分を抽出したりする場合に非常に便利です。
たとえば、`<<0, 1, rest::binary>> = <<0, 1, 2, 3>>`と記述することで、先頭の2バイトを分離し、残りを変数`rest`に格納できます。
バイナリパターンマッチは、特にプロトコル解析やデータ処理で役立ちます。
サイズの不明なデータや可変長のバイナリを扱う際も、柔軟に対応可能です。
また、`binary-size(n)`修飾子を用いることで、特定サイズのバイナリをマッチさせることができます。
このように、Elixirのバイナリパターンマッチングは、高度なデータ操作を直感的に行える強力なツールです。

パターンマッチの基本的な仕組みと構文

Elixirのバイナリパターンマッチは、`<<>>`構文内でデータを分割して変数に格納する仕組みです。
たとえば、`<> = <<1, 2, 3, 4>>`では、`a`が1、`b`が2、`c`が`<<3, 4>>`としてマッチします。
この簡潔な構文は、データの分解を効率化します。

binary修飾子を用いた柔軟なバイナリ操作

`binary`修飾子は、サイズの不明なバイナリを変数に格納する際に使用されます。
たとえば、`<>`と記述することで、最初のバイトを`head`に、残りを`rest`に格納できます。
この修飾子により、動的なデータ処理が可能になります。

バイナリパターンマッチの活用例とその効果

バイナリパターンマッチは、ファイルヘッダーの解析や通信プロトコルのデータ分解に最適です。
たとえば、画像ファイルのヘッダー情報を抽出したり、TCP/IPパケットを解析する際に効果を発揮します。
この機能により、複雑なデータ構造を簡潔に処理できます。

バイナリパターンマッチのエラーとその対処法

パターンマッチが失敗する場合は、`MatchError`が発生します。
このエラーを防ぐには、バイナリサイズを事前に検証したり、適切なデフォルト値を設定することが重要です。
これにより、予期せぬエラーを回避できます。

Elixirでのパターンマッチが得意とする場面

Elixirのパターンマッチは、固定長または可変長のバイナリデータを操作する場面で特に有用です。
たとえば、ネットワーク通信のデータ解析や、ログファイルから特定の情報を抽出するタスクに適しています。
この特性は、データ集約型のアプリケーション開発において非常に効果的です。

Elixirにおけるビット文字列とバイナリの違いと特徴

Elixirでは、バイナリはビット文字列の一種として扱われますが、特定の違いがあります。
バイナリはそのビット数が8の倍数でなければならないのに対し、ビット文字列は任意のビット数で構成できます。
このため、ビット文字列は、より柔軟にデータを表現する必要がある場合に使用されます。
ビット文字列もバイナリと同様にパターンマッチが可能です。
たとえば、`<>`のように、特定のビットサイズでデータを抽出できます。
これにより、細かなデータ操作が必要な場面、たとえば通信プロトコルのフラグ操作やビット単位のフラグ処理が簡単になります。
ビット文字列は、効率的なデータ操作を可能にするもう一つの強力なツールです。

ビット文字列とバイナリの基本的な定義と違い

ビット文字列は、任意のビット数で構成されるデータ型です。
一方、バイナリは8ビット単位で構成されます。
この違いにより、ビット文字列はバイナリよりも柔軟なデータ表現が可能です。

ビット文字列とバイナリの用途における具体的な違い

バイナリはファイル処理やネットワーク通信など、固定長のデータ操作に適しています。
一方、ビット文字列は通信プロトコルの解析や、フラグやビットフィールドの操作に適しています。

バイナリのパターンマッチがビット文字列にも有効な理由

バイナリとビット文字列は、どちらも`<<>>`構文を使用したパターンマッチが可能です。
この共通性により、どちらのデータ型でも直感的な操作が可能で、柔軟なデータ解析が実現します。

Elixirでビット文字列を使用する際の注意点

ビット文字列を使用する際は、ビット数が正しいかを確認する必要があります。
誤ったサイズ指定はエラーの原因となるため、事前に検証するか適切なデフォルト値を設定することが推奨されます。

ビット文字列とバイナリの組み合わせた実践例

たとえば、`<>`のようにビット文字列とバイナリを組み合わせることで、通信プロトコルのヘッダー解析や、データペイロードの抽出が効率的に行えます。
この柔軟性は、複雑なデータ操作を簡潔にする助けとなります。

Elixirでの文字リストとバイナリの違いについての詳細

Elixirでは、文字リストとバイナリは異なる用途で使用されますが、どちらも文字データを扱うために重要です。
文字リストはコードポイントのリストとして表現され、`’abc’`のようなシングルクォートで囲まれた構文で定義されます。
一方、バイナリはバイト列として定義され、UTF-8エンコードされた文字列として扱われます。
この違いは、データの扱いや処理方法に大きく影響します。
文字リストは、リストとしての操作が可能で、軽量なテキスト処理やエンコード不要の文字列データに適しています。
一方で、バイナリは効率的なメモリ使用を前提としており、大量の文字列データやバイナリデータを扱う場合に適しています。
これらのデータ型を理解し、適切に選択することで、より効率的なElixirプログラムを作成できます。

文字リストの基本的な定義とElixirにおける役割

文字リストは、各文字がUnicodeコードポイントとして格納されたリストで、`’abc’`のように記述します。
このリストは通常のElixirリストと同様に操作可能で、`[97, 98, 99]`と同義です。
特定のエンコードが不要な処理や、リスト操作が必要な場面で役立ちます。

バイナリと文字リストの内部構造の違い

バイナリはバイト列で構成され、メモリ効率に優れています。
一方、文字リストは各要素が整数値のリストであるため、メモリ消費が多くなる場合があります。
この違いにより、用途に応じた適切な選択が求められます。

文字リストとバイナリの変換方法とその用途

文字リストをバイナリに変換するには`List.to_string/1`、逆にバイナリを文字リストに変換するには`String.to_charlist/1`を使用します。
これにより、データ形式に応じた柔軟な操作が可能です。

Elixirでの文字リストとバイナリの使い分け方

文字リストは簡易的なテキスト処理に適しており、バイナリは大量データの効率的な処理に向いています。
ネットワーク通信やファイル操作ではバイナリが適していますが、シンプルな文字列処理では文字リストが便利です。

文字リストを扱う際のエラー回避のベストプラクティス

文字リストを扱う際には、データが期待通りの形式であるかを事前に検証することが重要です。
たとえば、リスト内の要素がすべて整数値であることを確認するか、デフォルト値を設定することで予期せぬエラーを防ぎます。

Elixirにおけるバイナリの有効性確認とその重要性

Elixirでは、バイナリが有効なUTF-8文字列かどうかを確認することが非常に重要です。
特に、ネットワーク通信や外部からのデータを扱う場合、データが正しい形式であることを保証することで、アプリケーションの信頼性を向上させることができます。
Elixirは、この確認を簡単に行うための`String.valid?/1`関数を提供しています。
`String.valid?/1`は、バイナリがUTF-8エンコードされた文字列であるかを判定します。
この関数を使用することで、不正なデータがアプリケーションに影響を及ぼす前にエラーを防ぐことができます。
特に、多言語対応のアプリケーションや、データの整合性が重要なシステムで役立ちます。

String.valid?関数の基本的な役割と使い方

`String.valid?/1`関数は、与えられたバイナリが有効なUTF-8文字列かを判定します。
たとえば、`String.valid?(<<104, 101, 108, 108, 111>>) # => true`となります。
このようにして、データの正当性を簡単に確認できます。

バイナリの有効性確認が重要な理由とその背景

ネットワーク通信や外部入力では、不正な形式のデータが流入する可能性があります。
これを放置すると、アプリケーションのエラーや脆弱性に繋がるため、事前に有効性を確認することが重要です。

UTF-8文字列として有効なバイナリの特性

UTF-8は可変長エンコードであり、文字ごとにバイト数が異なります。
有効なバイナリは、これらの規則に従っており、誤ったエンコードが含まれていません。
これを確認することで、データ処理が安全になります。

バイナリデータの検証を効率化する方法

バイナリデータを検証する際は、`String.valid?/1`を複数箇所で使用することで、エラー箇所を特定しやすくなります。
また、検証の結果をログに記録することで、問題の追跡も容易になります。

有効性確認を活用したエラー防止の実例

たとえば、ユーザーからの入力データを受け取る際に、`String.valid?/1`でバイナリを検証し、無効なデータはエラーメッセージとともに再入力を促すことで、アプリケーションの安定性を保つことができます。

バイナリのパターンマッチにおける具体的な使用例の解説

Elixirのバイナリパターンマッチは、バイナリデータを操作する際に非常に便利です。
たとえば、データの先頭部分を解析したり、特定の部分を抽出したりする場合に活用されます。
`<<0, 1, rest::binary>> = <<0, 1, 2, 3>>`のような構文を用いれば、先頭の2バイトを分離し、残りのデータを`rest`に格納することが可能です。
このような直感的な操作により、複雑なバイナリデータを簡単に扱うことができます。
特にネットワーク通信やプロトコルの解析では、バイナリパターンマッチが欠かせません。
サイズが不明なデータや、ヘッダーと本体が分かれているデータを処理する際に役立ちます。
また、`binary-size(n)`や`::little`などの修飾子を用いることで、さらに柔軟な操作が可能です。
これにより、Elixirはさまざまなデータ操作に対応できる強力なプログラミング言語として機能します。

Elixirでの<<>>構文を使ったバイナリ分割の例

Elixirでは、`<<>>`構文を使うことでバイナリを直感的に分割できます。
たとえば、`<> = binary_data`というコードを使えば、最初の4バイトをヘッダーとして抽出し、残りをボディに格納できます。
この分割方法は、固定長のヘッダーを持つプロトコル解析に適しています。

未知のサイズを持つバイナリのパターンマッチ方法

サイズが未知のバイナリを操作する場合、`<>`を使用すると便利です。
この構文は、バイナリの残りすべてを変数に格納します。
たとえば、`<> = <<1, 2, 3, 4>>`では、`prefix`に`1`が、`rest`に`<<2, 3, 4>>`が格納されます。

バイナリの先頭部分を抽出する具体例

バイナリの先頭部分を抽出するには、`<>`のようなパターンを使用します。
この方法により、先頭のバイトを変数`head`に格納し、残りを`rest`として扱うことができます。
このアプローチは、ヘッダー付きデータの解析に適しています。

パターンマッチのエラー発生時の対処方法

パターンマッチが失敗した場合、Elixirは`MatchError`をスローします。
このエラーを回避するには、マッチするデータのサイズや形式を事前に確認することが重要です。
たとえば、`byte_size/1`を使ってサイズを検証することで、エラーを未然に防ぐことができます。

複雑なバイナリパターンの操作を簡単にするテクニック

複雑なバイナリ操作を簡単にするために、バイナリパターンマッチを関数化するのが有効です。
たとえば、特定のフォーマットのデータを解析する関数を作成すれば、再利用性が高まり、コードの可読性も向上します。

Elixirにおけるバイナリとビット文字列の活用事例と違い

Elixirでは、バイナリとビット文字列を使い分けることで、さまざまな用途に対応できます。
バイナリは8ビットの倍数で構成されたデータ型で、主にファイル操作やネットワーク通信で使用されます。
一方、ビット文字列は任意のビット数で構成され、プロトコル解析やビット単位の操作に適しています。
この違いを理解することで、適切なデータ型を選択し、効率的なプログラムを構築できます。
たとえば、バイナリは文字列データや画像データを操作する場合に最適です。
一方で、ビット文字列はTCPヘッダー解析やフラグ操作など、より細かいデータ処理が必要な場面で活躍します。
また、両者を組み合わせることで、柔軟なデータ処理が可能となります。
この特性は、Elixirを使ったシステム開発において非常に有用です。

ビット文字列とバイナリの基本的な使い分け方

バイナリは固定長データを効率的に扱いたい場合に適しています。
一方、ビット文字列は、フラグやプロトコルのビット操作に最適です。
このような使い分けにより、パフォーマンスを最適化できます。

バイナリの操作とビット文字列の具体例

たとえば、`<>`のようにバイナリとビット文字列を組み合わせることで、通信データを効率的に解析できます。
この柔軟性は、プロトコル実装やデータ解析で大きな効果を発揮します。

バイナリとビット文字列を併用するメリット

両者を併用することで、固定長データと可変長データを同時に扱うことが可能になります。
これにより、通信プロトコルや複雑なデータフォーマットを簡潔に処理できます。

Elixirにおけるビット操作の重要性

ビット操作は、TCP/IPプロトコルやハードウェア制御など、低レベルのデータ処理において不可欠です。
Elixirのビット文字列は、この種の操作を簡単に実現できるため、非常に便利です。

バイナリとビット文字列を活用した応用例

たとえば、画像フォーマットの解析やカスタム通信プロトコルの実装で、バイナリとビット文字列を組み合わせることで、高い効率と柔軟性を実現できます。
この応用は、IoTやネットワークアプリケーションの開発において特に有用です。

資料請求

RELATED POSTS 関連記事