avro序列化詳細操作


Intellij 15.0.3
Maven
avro 1.8.0

Avro是一個數據序列化系統。
它提供以下:
1 豐富的數據結構類型
2 快速可壓縮的二進制數據形式
3 存儲持久數據的文件容器
4 遠程過程調用RPC
5 簡單的動態語言結合功能,Avro和動態語言結合后,讀寫數據文件和使用RPC協議都不需要生成代碼,而代碼生成作為一種可選的優化只值得在靜態類型語言中實現。
Avro依賴於模式(Schema)。Avro數據的讀寫操作是很頻繁的,而這些操作都需要使用模式,這樣就減少寫入每個數據資料的開銷,使得序列化快速而又輕巧。這種數據及其模式的自我描述方便於動態腳本語言的使用。

下面介紹如果使用avro進行序列化和反序列化的操作
前置條件:
maven項目

1、在pom.xml中添加avro的依賴包和編譯插件

1.1 配置avro依賴

在dependencies中配置avro的GAV

<dependency> <groupId>org.apache.avro</groupId> <artifactId>avro</artifactId> <version>1.8.0</version> </dependency>

1.2 在build–>plugins下配置編譯插件

<plugin> <groupId>org.apache.avro</groupId> <artifactId>avro-maven-plugin</artifactId> <version>1.8.0</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>schema</goal> </goals> <configuration> <sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory> <outputDirectory>${project.basedir}/src/main/java/</outputDirectory> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin>

2、定義avro的scheme

Avro scheme是通過JSON形式來定義的,一般以.avsc結尾(maven插件會去指定目錄下獲取.avsc結尾的文件並生成成Java文件)

2.1 在src/main目錄下新建一個avro文件夾

這里寫圖片描述

2.2 在src/main/avro目錄下新建一個文件,並保存為user.avsc。文件內容如下:

{"namespace": "cn.md31.avro.test.bean", "type": "record", "name": "User", "fields": [ {"name": "name", "type": "string"}, {"name": "favorite_number", "type": ["int", "null"]}, {"name": "favorite_color", "type": ["string", "null"]} ] }

其中
namespace在java項目中翻譯成包名
name是類名
fields就是配置的屬性
注意:必須配置type為record

2.3 生成User的java文件

avro提供了一個avro-tools包來生成java文件,可以通過下面命令:

java -jar /path/to/avro-tools-1.8.0.jar compile schema <schema file> <destination>
  • 1
  • 1

在1.2步中,pom文件中配置了插件,所以在maven項目中,我們只需要執行mvn complie 命令就可以自動生成java文件了。
注:插件會自動搜索src/main/avro目錄下的.avsc結尾的文件,並生成java文件到src/main/java包下
因為我們在pom文件中指定了相應目錄:

這里寫圖片描述

如果使用Intellij,我們直接執行compile即可:
這里寫圖片描述

執行之后會在相應目錄生成User.java文件
這里寫圖片描述

 

1 使用生成的User類初始化User對象

Avro自動生成的User類有三種方式初始化:

1.1 使用構造方法:

User user1 = new User("user1", 10, "red");

1.2 使用setter方法

User user2 = new User(); user2.setName("user2"); user2.setFavoriteNumber(11); user2.setFavoriteColor("white");
  • 1
  • 2

1.3 使用build方法

User user3 = User.newBuilder() .setName("user3") .setFavoriteNumber(12) .setFavoriteColor("black") .build();

整合到produceUsers方法中:

public static List<User> produceUsers() {
    List<User> userList = new ArrayList<User>(); // 三種初始化方式 User user1 = new User("user1", 10, "red"); User user2 = new User(); user2.setName("user2"); user2.setFavoriteNumber(11); user2.setFavoriteColor("white"); User user3 = User.newBuilder() .setName("user3") .setFavoriteNumber(12) .setFavoriteColor("black") .build(); userList.add(user1); userList.add(user2); userList.add(user3); return userList; }

2 把User對象序列化到文件中

public static void serializeAvroToFile(List<User> userList, String fileName) throws IOException { DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class); DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter); dataFileWriter.create(userList.get(0).getSchema(), new File(fileName)); for (User user: userList) { dataFileWriter.append(user); } dataFileWriter.close(); }

在main方法中調用上面兩個方法

public static void main(String[] args) throws IOException { List<User> userList = produceUsers(); String fileName = "users.avro"; serializeAvroToFile(userList, fileName); // deserializeAvroFromFile(fileName); // // byte[] usersByteArray = serializeAvroToByteArray(userList); // deserialzeAvroFromByteArray(usersByteArray); }

執行main方法,會發現在根目錄生成了一個users.avro文件:

這里寫圖片描述

3 從文件中反序列化對象

public static void deserializeAvroFromFile(String fileName) throws IOException { File file = new File(fileName); DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class); DataFileReader<User> dataFileReader = new DataFileReader<User>(file, userDatumReader); User user = null; System.out.println("----------------deserializeAvroFromFile-------------------"); while (dataFileReader.hasNext()) { user = dataFileReader.next(user); System.out.println(user); } }

執行之后得到結果:

這里寫圖片描述

4、序列化對象成byte 數組

public static byte[] serializeAvroToByteArray(List<User> userList) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class); DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter); dataFileWriter.create(userList.get(0).getSchema(), baos); for (User user: userList) { dataFileWriter.append(user); } dataFileWriter.close(); return baos.toByteArray(); }

5、從byte數組中反序列化成對象

public static void deserialzeAvroFromByteArray(byte[] usersByteArray) throws IOException { SeekableByteArrayInput sbai = new SeekableByteArrayInput(usersByteArray); DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class); DataFileReader<User> dataFileReader = new DataFileReader<User>(sbai, userDatumReader); System.out.println("----------------deserialzeAvroFromByteArray-------------------"); User readUser = null; while (dataFileReader.hasNext()) { readUser = dataFileReader.next(readUser); System.out.println(readUser); } }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM