javascript

java

python

c#

android

node.js

reactjs

c++

php

html

jquery

css

git

.net

ios

ruby-on-rails

sql

c

string

ruby

Java-在不损失质量的情况下调整图像大小

我有10,000张照片需要调整大小,所以我有一个Java程序可以做到这一点。 不幸的是,图像质量丢失得很严重,我无法访问未压缩的图像。

import java.awt.Graphics;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;


import javax.imageio.ImageIO;
/**
 * This class will resize all the images in a given folder
 * @author 
 *
 */
public class JavaImageResizer {

    public static void main(String[] args) throws IOException {

        File folder = new File("/Users/me/Desktop/images/");
        File[] listOfFiles = folder.listFiles();
        System.out.println("Total No of Files:"+listOfFiles.length);
        BufferedImage img = null;
        BufferedImage tempPNG = null;
        BufferedImage tempJPG = null;
        File newFilePNG = null;
        File newFileJPG = null;
        for (int i = 0; i < listOfFiles.length; i++) {
              if (listOfFiles[i].isFile()) {
                System.out.println("File " + listOfFiles[i].getName());
                img = ImageIO.read(new File("/Users/me/Desktop/images/"+listOfFiles[i].getName()));
                tempJPG = resizeImage(img, img.getWidth(), img.getHeight());
                newFileJPG = new File("/Users/me/Desktop/images/"+listOfFiles[i].getName()+"_New");
                ImageIO.write(tempJPG, "jpg", newFileJPG);
              }
        }
        System.out.println("DONE");
    }

    /**
     * This function resize the image file and returns the BufferedImage object that can be saved to file system.
     */
        public static BufferedImage resizeImage(final Image image, int width, int height) {
    int targetw = 0;
    int targeth = 75;

    if (width > height)targetw = 112;
    else targetw = 50;

    do {
        if (width > targetw) {
            width /= 2;
            if (width < targetw) width = targetw;
        }

        if (height > targeth) {
            height /= 2;
            if (height < targeth) height = targeth;
        }
    } while (width != targetw || height != targeth);

    final BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    final Graphics2D graphics2D = bufferedImage.createGraphics();
    graphics2D.setComposite(AlphaComposite.Src);
    graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
    graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
    graphics2D.drawImage(image, 0, 0, width, height, null);
    graphics2D.dispose();

    return bufferedImage;
}

我正在使用的图像是这样的:Firwork - original - large

这是我在Microsoft Paint中完成的手动大小调整:

resize - using Paint - small

这是我的程序[bilinear]的输出:

resize - using java program - small

更新:使用BICUBIC没有显着差异

这是我的程序的输出[bicubic]:

enter image description here

无论如何,可以提高程序输出的质量,因此我不必手动调整所有照片的大小?

先感谢您!

trans by 2019-11-19T03:06:45Z

java-如何确定代码是否在JUnit测试内运行?

在我的代码中,仅当它在JUnit测试中运行时,才需要进行某些修复。 如何确定代码是否在JUnit测试中运行? 是否有类似JUnit.isRunning()== true的东西?

trans by 2019-11-19T02:27:36Z

tomcat-以最少的停机时间部署Java Web应用程序的最佳实践?

部署大型Java Web应用程序(> 100 MB .war)时,当前正在使用以下部署过程:

  • 应用程序.war文件在开发计算机上本地扩展。
  • 扩展后的应用程序是从开发机到实时环境的rsync:ed。
  • rsync之后,实时环境中的应用程序服务器将重新启动。 并非必须严格执行此步骤,但是我发现由于频繁加载类,在部署时重新启动应用程序服务器可避免出现“ java.lang.OutOfMemoryError:PermGen space”。

关于这种方法的好处:

  • rsync可以最大程度地减少从开发机发送到实时环境的数据量。 上载整个.war文件需要十多分钟,而rsync则需要几秒钟。

这种方法的坏事:

  • 在rsync运行时,由于文件已更新,因此将重新启动应用程序上下文。 理想情况下,重新启动应在rsync完成后进行,而不是在仍在运行时进行。
  • 应用服务器重启将导致大约两分钟的停机时间。

我想找到一个具有以下属性的部署过程:

  • 部署过程中的停机时间最少。
  • 花费最少的时间上传数据。
  • 如果部署过程是特定于应用程序服务器的,则该应用程序服务器必须是开源的。

题:

  • 给定所述要求,最佳部署过程是什么?
trans by 2019-11-19T01:57:48Z

枚举名称是否在Java中被保留?

枚举名称是否在Java中被保留?

即 是否保证enum1.name() == enum2.name()具有相同的名称? 比较安全的是将enum.name()与保证可以嵌入的字符串进行比较是安全的。

trans by 2019-11-19T01:24:45Z

Java Unicode字符串长度

我正在努力获取unicode字符串的计数,并尝试了各种选择。 看起来像是一个小问题,但却大有作为。

在这里,我试图获取字符串str1的长度。 我得到的是6。但实际上是3。将光标移到字符串“குமார்”上还会显示为3个字符。

基本上,我想测量长度并打印每个字符。 如“கு”,“மா”,“ர்”。

 public class one {
    public static void main(String[] args) {
            String str1 = new String("குமார்");
            System.out.print(str1.length());
    }
}

PS:这是泰米尔语。

trans by 2019-11-19T01:03:15Z

java-当catch实际上没有捕获任何东西时

这个问题在这里已有答案:

  • “比较方法违反了其一般合同!”                                     11个答案

最近由于数据库中存储的数据不正确,导致程序崩溃。 这让我感到困惑,因为我以为我可以防止这种情况发生。

以下代码的目的是比较员工证件编号并对其进行排序。 如果有错误,请返回-1,然后继续使用士兵-不要停止,因为数千个徽章编号之一是错误的:

public int compare(Employee t, Employee t1) {
    Integer returnValue = -1;
    try {
        Integer tb = Integer.parseInt(t.getBadgeNumber());
        Integer t1b = Integer.parseInt(t1.getBadgeNumber());
        returnValue = tb.compareTo(t1b);
    } catch (Exception e) {
        returnValue = -1;//useless statement, I know.
    }
    return returnValue;
}

当错误的徽章编号命中时(在这种情况下为t),我得到了一个“ java.lang.IllegalArgumentException:比较方法违反了它的常规约定!” 错误,而不是在catch中返回-1。

我对这里的渔获物不了解?

完整的堆栈跟踪:

16-May-2018 14:28:53.496 SEVERE [http-nio-8084-exec-601] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [RequestServlet] in context with path [/AppearanceRequest] threw exception
 java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeForceCollapse(TimSort.java:426)
at java.util.TimSort.sort(TimSort.java:223)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
at org.bcso.com.appearancerequest.html.NotifierHTML.getHTML(NotifierHTML.java:363)
at org.bcso.com.appearancerequest.AppearanceRequestServlet.processRequest(AppearanceRequestServlet.java:96)
at org.bcso.com.appearancerequest.AppearanceRequestServlet.doGet(AppearanceRequestServlet.java:565)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:301)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:74)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1015)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:652)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1575)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1533)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)

调用代码:

    List<Employee> employeeList = DatabaseUtil.getEmployees();
    Collections.sort(employeeList, new BadgeComparator());
trans by 2019-11-18T20:19:12Z

java-Spring REST Service:如何配置为在JSON响应中删除空对象

我有一个春天的Web服务,返回一个JSON响应。 我使用此处给出的示例创建服务:[http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/]

返回json的格式为:{“名称”:null,“ staffName”:[“ kfc-kampar”,“史密斯”]}

我想从返回的响应中删除任何空对象,所以它看起来像这样:{“ staffName”:[“ kfc-kampar”,“史密斯”]}

我在这里发现了类似的问题,但我已经能够找到解决方案,例如

在Spring中配置ObjectMapper

在使用基于Spring注释的配置时如何配置MappingJacksonHttpMessageConverter?

配置jacksonObjectMapper在Spring MVC 3中不起作用

如何配置Spring MVC 3在JSON响应中不返回“空”对象?

Spring配置@ResponseBody JSON格式

Jackson + Spring3.0.5自定义对象映射器

通过阅读这些和其他资料,我发现实现我想要的最干净的方法是使用Spring 3.1和可以在mvc-annotation中配置的消息转换器。我更新的spring配置文件是:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

<context:component-scan base-package="com.mkyong.common.controller" />

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="prefixJson" value="true" />
            <property name="supportedMediaTypes" value="application/json" />
            <property name="objectMapper">
                <bean class="org.codehaus.jackson.map.ObjectMapper">
                    <property name="serializationInclusion" value="NON_NULL"/>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

该服务类别与mkyong.com网站上提供的服务类别相同,除了我注释掉了Shop name变量的设置,因此它为空,即。

@Controller
@RequestMapping("/kfc/brands")
public class JSONController {
    @RequestMapping(value="{name}", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK) 
    public @ResponseBody Shop getShopInJSON(@PathVariable String name) {
        Shop shop = new Shop();
        //shop.setName(name);
        shop.setStaffName(new String[]{name, "cronin"});
        return shop;
    }
}

我正在使用的Jackson罐子是jackson-mapper-asl 1.9.0和jackson-core-asl 1.9.0。 这些是我从mkyong.com下载的spring-json项目的一部分,是我添加到pom中的唯一新罐。

该项目成功构建,但是当我通过浏览器调用服务时,我仍然得到相同的信息,即{“名称”:null,“ staffName”:[“ kfc-kampar”,“史密斯”]}

谁能告诉我我的配置哪里出问题了?

我已经尝试了其他几种选择,但是我能够以正确格式返回json的唯一方法是将Object映射器添加到JSONController并让“ getShopInJSON”方法返回字符串,即

public @ResponseBody String getShopInJSON(@PathVariable String name) throws JsonGenerationException, JsonMappingException, IOException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);

    Shop shop = new Shop();
    //shop.setName(name);
    shop.setStaffName(new String[]{name, "cronin"});
    String test = mapper.writeValueAsString(shop);
    return test;
}

现在,如果我调用该服务,我将得到预期的结果。{“ staffName”:[“ kfc-kampar”,“ cronin”]}

我还可以使用@JsonIgnore批注使其正常工作,但是该解决方案不适合我。

我不明白为什么它可以在代码中工作,但不能在配置中工作,所以任何帮助都是很棒的。

trans by 2019-11-18T20:12:07Z

性能-Java反射的更快替代方案

众所周知,反射是一种灵活但缓慢的方法,可以在运行时维护和修改代码的行为。

但是,如果我们必须使用这种功能,那么与用于动态修改的Reflection API相比,Java中是否有更快的编程技术? 这些替代方法对抗反射的利弊是什么?

trans by 2019-11-18T18:40:16Z

集合-Java 8流映射到按值排序的键列表

我有映射Map<Type, Long> countByType,我想要一个列表,其中按其对应的值对键(最小到最大)进行了排序。 我的尝试是:

countByType.entrySet().stream().sorted().collect(Collectors.toList());

但这只是给我一个条目列表,如何在不丢失顺序的情况下获取类型列表?

trans by 2019-11-18T18:28:11Z

getter setter-(否)Java中的属性?

因此,直到最近我还是故意为自己保留Java n00b,而我的第一次实际接触却引起了轻微的震惊:Java没有C#样式属性!

好吧,我可以接受。 但是,我也可以发誓我已经在一个代码库中看到了Java中的属性获取器/设置器代码,但是我不记得在哪里。 那是如何实现的? 是否有语言扩展? 它与NetBeans有关吗?

trans by 2019-11-18T18:17:42Z

为什么Java中的抽象类具有构造函数?

这个问题在这里已有答案:

  • 抽象类可以有构造函数吗?                                     22个答案

为什么Java中的abstract类具有constructor

我们无法实例化abstract类,它的构造是什么?

有什么想法吗?

trans by 2019-11-18T17:40:05Z

Scala与Java构建器模式等效吗?

在我每天用Java进行的工作中,我为流畅的接口使用了大量构建器,例如:onTopOf(base:Base)

使用快速而又肮脏的Java方法,每个方法调用都会使构建器实例发生变异,并返回onTopOf(base:Base)。不可变地,它涉及更多的类型输入,首先在修改构建器之前对其进行克隆。 构建方法最终会在构建器状态上进行繁重的工作。

在Scala中实现相同目标的一种好方法是什么?

如果我想确保只调用一次onTopOf(base:Base),然后再调用with(ingredient:Ingredient)build():Pizza,这是一个定向构建器,那么我将如何处理呢?

trans by 2019-11-18T17:12:52Z

java-等到Future <T>中的任何一个成为don

我运行的异步任务很少,我需要等到至少其中一个完成为止(将来可能需要等待N个任务中的util M完成)。目前,它们以“未来”的形式出现,所以我需要类似

/**
 * Blocks current thread until one of specified futures is done and returns it. 
 */
public static <T> Future<T> waitForAny(Collection<Future<T>> futures) 
        throws AllFuturesFailedException

有没有这样的东西? 或类似的东西,对于Future来说不是必需的。 目前,我循环浏览期货,检查一项是否完成,然后入睡一段时间,然后再次检查。 这似乎不是最佳解决方案,因为如果我长时间睡眠,则会增加不必要的延迟;如果我短期睡眠,则会影响性能。

我可以尝试使用

new CountDownLatch(1)

并在任务完成时减少倒计时

countdown.await()

,但我发现只有在我控制Future创建时才有可能。 这是可能的,但需要重新设计系统,因为当前任务创建的逻辑(将Callable发送给ExecutorService)与决定等待哪个Future分开。 我也可以覆盖

<T> RunnableFuture<T> AbstractExecutorService.newTaskFor(Callable<T> callable)

并创建RunnableFuture的自定义实现,并具有将任务完成时通知的附加侦听器,然后将此类侦听器附加到所需任务并使用CountDownLatch的功能,但这意味着我必须为我使用的每个ExecutorService覆盖newTaskFor-可能会有实现 不会扩展AbstractExecutorService。 我也可以尝试出于相同的目的包装给定的ExecutorService,但随后我必须装饰产生Futures的所有方法。

所有这些解决方案可能都有效,但看起来非常不自然。 似乎我缺少一些简单的东西,例如

WaitHandle.WaitAny(WaitHandle[] waitHandles)

在C#中。 是否有针对此类问题的知名解决方案?

更新:

最初,我根本无法使用Future创作,因此没有优雅的解决方案。 重新设计系统后,我可以访问Future创建并能够将countDownLatch.countdown()添加到执行过程中,然后我可以countDownLatch.await()正常运行。感谢您提供其他答案,我不知道ExecutorCompletionService,它确实对类似的任务有帮助,但是在这种特殊情况下,由于某些Futures没有任何执行程序就创建了,因此无法使用它-实际任务通过网络发送到另一台服务器, 远程完成并收到完成通知。

trans by 2019-11-18T16:32:25Z

Java中用于文本字符串的64位哈希函数是什么?

我正在寻找一个散列函数:

  1. 很好地哈希文本字符串(例如,很少冲突)
  2. 用Java编写,并被广泛使用
  3. 奖金:适用于多个字段(而不是我将它们串联并在连接的字符串上应用哈希)
  4. 奖励:具有128位变量。
  5. 奖励:不占用CPU。
trans by 2019-11-18T15:53:18Z

Java:检查当前字符串的日期格式是否符合要求的格式或n

这个问题在这里已有答案:

  • 如何理智地检查Java中的日期                                     21个答案

我想知道Java中有什么方法可以做到这一点,否则我可能会去Regex解决方案。

我从用户输入的字符串可以是任何字符。 我想检查输入的字符串是否符合我要求的日期格式。

由于我输入了20130925,而我所需的格式是dd / MM / yyyy,因此,在这种情况下,我应该得到false。

我不想转换此日期,我只想检查输入的字符串是否符合所需的日期格式。



我尝试了以下

Date date = null;
try {
date = new SimpleDateFormat("dd/MM/yyyy").parse("20130925");
} catch (Exception ex) {
// do something for invalid dateformat
}

但是我的catch(ex ex)块无法捕获SimpleDateFormat.Parse();生成的任何异常;

trans by 2019-11-18T12:21:02Z

java-ArrayList和LinkedList之间的性能差异

是的,这是一个古老的话题,但是我仍然有些困惑。

在Java中,人们说:

  1. 如果我随机访问它的元素,ArrayList比LinkedList快。 我认为随机访问的意思是“给我第n个元素”。 为什么ArrayList更快?

  2. LinkedList的删除速度比ArrayList快。 我明白这一点。 ArrayList的速度较慢,因为需要重新分配内部备份阵列。 代码说明:

    List<String> list = new ArrayList<String>();
    list.add("a");
    list.add("b");
    list.add("c");
    list.remove("b");
    System.out.println(list.get(1)); //output "c"
    
  3. LinkedList的插入速度比ArrayList的快。 插入在这里是什么意思? 如果这意味着要将某些元素移回然后将其放在中间的空白位置,则ArrayList应该比LinkedList慢。 如果插入仅意味着add(Object)操作,这怎么会慢呢?

trans by 2019-11-18T10:29:33Z

java-检查布尔数组中的所有值是否都为真的最优雅的方法是什么?

我在Java中有一个布尔数组:

boolean[] myArray = new boolean[10];

检查所有值是否为真的最优雅的方法是什么?

trans by 2019-11-18T08:43:51Z

为什么要声明一个函数参数为final?

目前,我正在研究Sams出版的《 24小时自学Android应用程序开发》一书。 我是Java,Android或其他方面的新手。 我在ActionScript 3中有非常扎实的背景,它与Java有足够的相似性,因此语言本身并不难掌握,但对于本书中某些代码示例的基本原理,我仍有一些疑问。 例如,以下是第9小时的示例代码附带的函数:

private void processScores(final TableLayout scoreTable, 
      XmlResourceParser scores) throws IOException, XmlPullParserException{

在此函数签名中,作者已将scoreTable参数声明为final。 我为他们为什么这么做感到困惑。 甚至没有尝试为函数参数scoreTable分配新值的想法(在ActionScript中认为这是一种不好的做法)。 此外,在我研究或移植到AS3的任何实际Java中,我实际上都没有看到任何人这样做。

关于Android开发,是否有某些特定要求使得有时需要将某些函数参数声明为final?

为什么将TableLayout对象声明为final,而不声明为XmlResourceParser?

trans by 2019-11-18T08:34:26Z

java-IdentityHashMap的用例

谁能告诉我IdentityHashMap的重要用例是什么?

trans by 2019-11-18T06:40:15Z

java-每个日志条目带有时间戳的log4j

这是我的日志输出

INFO main digestemails - process inbox
INFO main digestemails - checking for emails in c:\development\DCMail\email\KN-Source
INFO main digestemails - digesting 003d01c95a7b_3446880_0202fea9@xxxx.com.eml
INFO main digestemails - extracting attachments
INFO main digestemails - no attachments or no attachments supported
INFO main digestemails - updating database
INFO main digestemails - email -> COMPLETED folder
INFO main digestemails -  

我想要每个日志消息的时间戳,即

INFO 2008-12-25 13:14:00 digestemails - email -> COMPLETED folder

这是我的log4j配置文件

log4j.rootLogger=debug, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=c:\\development\\DCMail\\logs\\digestlogfolder\\digest-logfile.log

log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n 

我该怎么做?

trans by 2019-11-18T06:20:28Z

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 下一页 共310页